From 5f8263eb0af86d791ade99bec79c0370fea44b99 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Thu, 25 Jul 2024 15:46:15 +0100 Subject: [PATCH 01/32] define schemas, remove write_md and produc_graph bool parameters --- CHANGELOG.md | 6 + cmem_plugin_reason/plugin_reason.py | 20 +++- cmem_plugin_reason/plugin_validate.py | 65 +++++------ cmem_plugin_reason/utils.py | 2 +- poetry.lock | 159 +++++++++++++------------- tests/test_reason.py | 2 - 6 files changed, 130 insertions(+), 124 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 168b39d..59ef909 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ## [Unreleased] + +### Added + + - defined input and output schema + ### Changed - raise OSError on post result graph error +- removed write_md and produce_graph bool parameters ## [1.0.0beta4] 2024-07-12 diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index 66dc6b2..ad4ef8f 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -12,9 +12,10 @@ from cmem.cmempy.dp.proxy.graph import get from cmem_plugin_base.dataintegration.context import ExecutionContext from cmem_plugin_base.dataintegration.description import Icon, Plugin, PluginParameter -from cmem_plugin_base.dataintegration.entity import Entities +from cmem_plugin_base.dataintegration.entity import Entities, EntityPath, EntitySchema from cmem_plugin_base.dataintegration.parameter.graph import GraphParameterType from cmem_plugin_base.dataintegration.plugins import WorkflowPlugin +from cmem_plugin_base.dataintegration.ports import FixedNumberOfInputs, FixedSchemaPort from cmem_plugin_base.dataintegration.types import BoolParameterType, StringParameterType from cmem_plugin_base.dataintegration.utils import setup_cmempy_user_access from urllib3.exceptions import InsecureRequestWarning @@ -184,12 +185,12 @@ class ReasonPlugin(WorkflowPlugin): """Reason plugin""" - def __init__( # noqa: PLR0913 + def __init__( # noqa: PLR0913, C901 self, data_graph_iri: str = "", ontology_graph_iri: str = "", output_graph_iri: str = "", - reasoner: str = "elk", + reasoner: str = "", class_assertion: bool = False, data_property_characteristic: bool = False, disjoint_classes: bool = False, @@ -265,6 +266,19 @@ def __init__( # noqa: PLR0913 self.input_profiles = input_profiles self.max_ram_percentage = max_ram_percentage + if input_profiles: + self.input_ports = FixedNumberOfInputs([FixedSchemaPort(self.generate_input_schema())]) + else: + self.input_ports = FixedNumberOfInputs([]) + self.output_port = FixedSchemaPort(EntitySchema(type_uri="", paths=[])) + + def generate_input_schema(self) -> EntitySchema: + """Generate the output schema.""" + return EntitySchema( + type_uri="urn:row", + paths=[EntityPath(path="profile"), EntityPath(path="ontology")], + ) + def get_graphs(self, graphs: dict, context: ExecutionContext) -> None: """Get graphs from CMEM""" for graph in graphs: diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index 73c482c..55ac901 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -12,13 +12,9 @@ from cmem.cmempy.workspace.projects.resources.resource import create_resource from cmem_plugin_base.dataintegration.context import ExecutionContext from cmem_plugin_base.dataintegration.description import Icon, Plugin, PluginParameter -from cmem_plugin_base.dataintegration.entity import ( - Entities, - Entity, - EntityPath, - EntitySchema, -) +from cmem_plugin_base.dataintegration.entity import Entities, Entity, EntityPath, EntitySchema from cmem_plugin_base.dataintegration.plugins import WorkflowPlugin +from cmem_plugin_base.dataintegration.ports import FixedNumberOfInputs, FixedSchemaPort from cmem_plugin_base.dataintegration.types import BoolParameterType, StringParameterType from cmem_plugin_base.dataintegration.utils import setup_cmempy_user_access from pathvalidate import is_valid_filename @@ -59,20 +55,6 @@ ONTOLOGY_GRAPH_IRI_PARAMETER, MAX_RAM_PERCENTAGE_PARAMETER, VALIDATE_PROFILES_PARAMETER, - PluginParameter( - param_type=BoolParameterType(), - name="write_md", - label="Write Markdown explanation file", - description="Write Markdown file with explanation to project.", - default_value=False, - ), - PluginParameter( - param_type=BoolParameterType(), - name="produce_graph", - label="Produce output graph", - description="Produce explanation graph.", - default_value=False, - ), PluginParameter( param_type=StringParameterType(), name="output_graph_iri", @@ -104,9 +86,7 @@ def __init__( # noqa: PLR0913 self, ontology_graph_iri: str = "", reasoner: str = "elk", - produce_graph: bool = False, output_graph_iri: str = "", - write_md: bool = False, md_filename: str = "", validate_profile: bool = False, stop_at_inconsistencies: bool = False, @@ -115,13 +95,13 @@ def __init__( # noqa: PLR0913 errors = "" if not validators.url(ontology_graph_iri): errors += 'Invalid IRI for parameter "Ontology graph IRI." ' - if produce_graph and not validators.url(output_graph_iri): + if output_graph_iri and not validators.url(output_graph_iri): errors += 'Invalid IRI for parameter "Output graph IRI". ' - if produce_graph and output_graph_iri == ontology_graph_iri: + if output_graph_iri and output_graph_iri == ontology_graph_iri: errors += "Output graph IRI cannot be the same as the Ontology graph IRI. " if reasoner not in REASONERS: errors += 'Invalid value for parameter "Reasoner". ' - if write_md and not is_valid_filename(md_filename): + if md_filename and not is_valid_filename(md_filename): errors += 'Invalid filename for parameter "Output filename". ' if max_ram_percentage not in range(1, 101): errors += 'Invalid value for parameter "Maximum RAM Percentage". ' @@ -129,14 +109,16 @@ def __init__( # noqa: PLR0913 raise ValueError(errors[:-1]) self.ontology_graph_iri = ontology_graph_iri self.reasoner = reasoner - self.produce_graph = produce_graph self.output_graph_iri = output_graph_iri - self.write_md = write_md self.stop_at_inconsistencies = stop_at_inconsistencies - self.md_filename = md_filename if write_md else "mdfile.md" + self.md_filename = md_filename if md_filename else "mdfile.md" self.validate_profile = validate_profile self.max_ram_percentage = max_ram_percentage + self.input_ports = FixedNumberOfInputs([]) + self.schema = self.generate_output_schema() + self.output_port = FixedSchemaPort(self.schema) + def get_graphs(self, graphs: dict, context: ExecutionContext) -> None: """Get graphs from CMEM""" for graph in graphs: @@ -156,7 +138,7 @@ def explain(self, graphs: dict) -> None: f'--explanation "{self.temp}/{self.md_filename}"' ) - if self.produce_graph: + if self.output_graph_iri: cmd += ( f' annotate --ontology-iri "{self.output_graph_iri}" ' f'--language-annotation rdfs:label "Ontology Validation Result {utctime}" en ' @@ -191,28 +173,32 @@ def add_profiles(self, valid_profiles: list) -> list: if valid_profiles: profiles_str = "\n- ".join(valid_profiles) mdfile.write(f"- {profiles_str}\n") - if self.produce_graph: + if self.output_graph_iri: post_profiles(self, valid_profiles) return valid_profiles + def generate_output_schema(self) -> EntitySchema: + """Generate the output schema.""" + paths = [EntityPath(path="markdown"), EntityPath(path="ontology")] + if self.validate_profile: + paths.append(EntityPath(path="profile")) + return EntitySchema( + type_uri="https://eccenca.com/plugin_validateontology/type", + paths=paths, + ) + def make_entities(self, text: str, valid_profiles: list) -> Entities: """Make entities""" values = [[text], [self.ontology_graph_iri]] - paths = [EntityPath(path="markdown"), EntityPath(path="ontology")] if self.validate_profile: values.append(valid_profiles) - paths.append(EntityPath(path="profile")) entities = [ Entity( uri="https://eccenca.com/plugin_validateontology/result", values=values, ), ] - schema = EntitySchema( - type_uri="https://eccenca.com/plugin_validateontology/type", - paths=paths, - ) - return Entities(entities=entities, schema=schema) + return Entities(entities=entities, schema=self.schema) def _execute(self, context: ExecutionContext) -> Entities: """Run the workflow operator.""" @@ -222,7 +208,7 @@ def _execute(self, context: ExecutionContext) -> Entities: create_xml_catalog_file(self.temp, graphs) self.explain(graphs) - if self.produce_graph: + if self.output_graph_iri: setup_cmempy_user_access(context.user) send_result(self.output_graph_iri, Path(self.temp) / "output.ttl") setup_cmempy_user_access(context.user) @@ -232,7 +218,8 @@ def _execute(self, context: ExecutionContext) -> Entities: self.add_profiles(validate_profiles(self, graphs)) if self.validate_profile else [] ) - if self.write_md: + # if self.write_md: + if self.md_filename: setup_cmempy_user_access(context.user) self.make_resource(context) diff --git a/cmem_plugin_reason/utils.py b/cmem_plugin_reason/utils.py index bd195aa..94dcef4 100644 --- a/cmem_plugin_reason/utils.py +++ b/cmem_plugin_reason/utils.py @@ -45,7 +45,7 @@ name="reasoner", label="Reasoner", description="Reasoner option.", - default_value="elk", + default_value="", ) MAX_RAM_PERCENTAGE_PARAMETER = PluginParameter( diff --git a/poetry.lock b/poetry.lock index c32d200..c47eca0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -485,48 +485,48 @@ files = [ [[package]] name = "memray" -version = "1.13.3" +version = "1.13.4" description = "A memory profiler for Python applications" optional = false python-versions = ">=3.7.0" files = [ - {file = "memray-1.13.3-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:47d2eb555d24e006cd6bac4390627ff227387a9e5cbc4257b08b2842ca202763"}, - {file = "memray-1.13.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0b32061ef473c35feccf2b65771b3b803bd9f7c2b1c31499ce8dac892f6cb79b"}, - {file = "memray-1.13.3-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:bc5cdde5c0db11bb52ccffe0a155a4324db2d8ffe5a82d222cdc31eea09d927e"}, - {file = "memray-1.13.3-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8f2856d392e60de240cd024843a4a7902644a2064562390196ad11b87f08e5ed"}, - {file = "memray-1.13.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c644b9408bec95cd66bc1184c46a5dfc084e5305f2b764213bef3438bc75bf63"}, - {file = "memray-1.13.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e4637da6a98ba546daccc5d033d82f67e8ee1d3e683e8c4d92c4dae94ccf57e9"}, - {file = "memray-1.13.3-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:3d1bbe9208ad5f73c1e327fbe7c42cce4b22a2c656f876944449f817a6f2645c"}, - {file = "memray-1.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26849671728dfbd09c46cfe62e01acb51e6322bc33e3478143d91a5f6b19b6f8"}, - {file = "memray-1.13.3-cp311-cp311-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d6673df94ddb3216b3ea35ece621e496fcbbaf886edddd2390d63f896a625f55"}, - {file = "memray-1.13.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86f4ab3d99e3747da26a3ba18884db86ac231789133227a50a8925eceda75c1e"}, - {file = "memray-1.13.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c031896590c9b2ec68dcbe05d2d32f4dba1757a46aaffa725a1505afdf956eae"}, - {file = "memray-1.13.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a61155b9b562ffd8485bf171fc656bdb44d429036f90d1739b5d13f9b8c2e50d"}, - {file = "memray-1.13.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:348e06153a2a582019e07c2f773339d64fac6807a05e9c7569c3281215ce5ed4"}, - {file = "memray-1.13.3-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:7377760d9996e92a07bfa9ff4f1d9144c3bc64d144846363fe3b0a19594141f2"}, - {file = "memray-1.13.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fb77a2b05e22496657cff0692161b2494da69b83d250754377861c484b0f58a6"}, - {file = "memray-1.13.3-cp312-cp312-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:18fb9a6288fcdf054f9130eb94cf029bd69670b5cf961fd670ae02b8dad19331"}, - {file = "memray-1.13.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:772139fbbe48d7a47946b0916ca7c1e20f2d4ae5112dc6e372cce7d997238d81"}, - {file = "memray-1.13.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd064c4bf3e58c872d597036c3c9d4cfd0e360e9b18c22a601864f484771ffd4"}, - {file = "memray-1.13.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5627ccca0b9b9fcc1a2596486f969d8505dcc7587c73d8b58710aff96ffe3b1"}, - {file = "memray-1.13.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b1b5e5f33000fe454219f6d3ecc5179d3de667baf4de0438bba5524e7cee62c0"}, - {file = "memray-1.13.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5ef12dbe43815d2b362e32f7672cb8d4a4b89d3e16b1f6272ac34aa4f56ef97e"}, - {file = "memray-1.13.3-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c796471031ed8d300317141f96308abd6550c5b8d4dd4aebafa07d3c1d193ab8"}, - {file = "memray-1.13.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc1b6569fdcc352bddf5433bd000b9db4bd5441e9c4afb0c15bdc409370e8cf3"}, - {file = "memray-1.13.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5828292b53e52c7b77872c351a97d85cc261d6c38f4b6af3b1943591e86151c1"}, - {file = "memray-1.13.3-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:3912adfd99dd8d37d15c5f1f4e2a7e6d9f06db03257a4f25e6da6b87d8dac604"}, - {file = "memray-1.13.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6ec6ee4197304557c068e9cf0aef9299d9eea414e106d6aef6fb9bca32b88c5f"}, - {file = "memray-1.13.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c4160dd66cd69ef1ad2989b72394c71227b81178deba3ef3941af6055e41feec"}, - {file = "memray-1.13.3-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7fe9f9a19e22faa1a4101c6c0804b6d8cb6a0e6d040a6e91c4b4f07c88cad7d1"}, - {file = "memray-1.13.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81d9bbd33856a47800301dbbc5ae51d499107a2cf41542a400d26d7be0ce3c74"}, - {file = "memray-1.13.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a7419cd8acf5d2e460f70ae62396e65a79cfd3262a655b5fd753a0ef0dee4bc4"}, - {file = "memray-1.13.3-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:549cf4b6ab259bfefabe8b5c688c21d21e3ef6b5e7f9123deee54d84d1334c5d"}, - {file = "memray-1.13.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8fcc112ed76c3e9d3b1d992fe97e079f51267c601b22bc292ed8a7bc961bd3af"}, - {file = "memray-1.13.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37b87a8ea3e2910286ff6f21dcef7a0044e753a18f6a987a085b728a0ded8f7b"}, - {file = "memray-1.13.3-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f17a4e7c1bd0ed1f890cdc3447567801296b2857b4250d1cd23c40ec929cc50f"}, - {file = "memray-1.13.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:071c5b44ae52f583ba62af0a2cdaeea72a1c2c9513aba53873e32827becc4e1a"}, - {file = "memray-1.13.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b50ee1121b300371a5686a10fb3ed1a3711fa4fadacb198140e537beb43f176e"}, - {file = "memray-1.13.3.tar.gz", hash = "sha256:3810a5dbafdf91d967255d6ee1ed82928bcbfaf56821eb8745cd630947140281"}, + {file = "memray-1.13.4-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:ed0bfcffbd857cbf78a4db942019e9e153019b754048b0522065844d1c538e8c"}, + {file = "memray-1.13.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fcf71802b2c6d68c5336b1e4ae341eab64dcccd0dcf67687af53f18bc020237b"}, + {file = "memray-1.13.4-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6c9ae675131492bdfafcc44e86d0b81401ea8d052a9cab7793b1dab642cd58e6"}, + {file = "memray-1.13.4-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bac9d30ce39aaee40601087d09c1639a071293f414b5e726a152ed3581d25e50"}, + {file = "memray-1.13.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a437c7e28734028a2f43f942c3146e9737033718cea092ea910f6de3cf46221d"}, + {file = "memray-1.13.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3cae161d5b6769cc3af574cfa0c7ea77f98d6ae714ba5ec508f6f05b84800801"}, + {file = "memray-1.13.4-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:bf407123e175de4f5a7264886eb64ea514f4b388b617f05dfcd857d99ecadd1c"}, + {file = "memray-1.13.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a6f1bd3d0adf84f864e24f74552c1533224e64283dfee33641011acf384fc138"}, + {file = "memray-1.13.4-cp311-cp311-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ba5bb9a3b7c3c08752f3b55a3b5b360963c9f666e2220eb388ab6f7d1271d843"}, + {file = "memray-1.13.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1e8cec70e51e81c0e9448e62a5366914b74a3dbb60826cdec8f0e7559e58e74"}, + {file = "memray-1.13.4-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81497e578017feb57a46e19c349450888e57ff7fb8f0f5134d3e07605c435500"}, + {file = "memray-1.13.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e585d866c82ce92060fa1c925298aa8b89936ca22df9698a25a5f0cf7ca81fa2"}, + {file = "memray-1.13.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3d048da01dc138711a2c9c70ba693d186690c98fb0ca26fdc3483486d4849238"}, + {file = "memray-1.13.4-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:b6459761046ab46638d2c62d7f3f55eaaf45a947bd1d36dcfb5e860047280557"}, + {file = "memray-1.13.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:637651f5ca2870e9156f189c337e8c6d0002e3f6f7d44d6486ff5baf12a6115e"}, + {file = "memray-1.13.4-cp312-cp312-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d5b9e10fde6f652ea176cbc0d4d4c563d2831faec4434d3e03c4c0aff8ddc6c0"}, + {file = "memray-1.13.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1f3ab803b703b9be29259039caf43803ad5abf37f04e77cd9e8373054dd91f6"}, + {file = "memray-1.13.4-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfdc070da2df9241f78b7429d44f6ee16e924d43eddc587f6ed7218c4cb792d3"}, + {file = "memray-1.13.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:523a63dee71cd4d55eddca866244a045e7549ca5137ec906c62893b87a2161ce"}, + {file = "memray-1.13.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3bf06f8883a26b779cc828addad97a2d39d7587263e348655dae3ec90b6ee079"}, + {file = "memray-1.13.4-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ee47b798d5712faa2a38ff60b5c77f73ed8342709e15bd6ed3a46edd9feee089"}, + {file = "memray-1.13.4-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:daed9ae6ceea6a4dcc96ac62cfa00d90f7365ed54ee90886e5287251855a2c02"}, + {file = "memray-1.13.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc194c5564f5b33d33bbbeca54b0e3f637d985a144c3551f887bf668d896ffec"}, + {file = "memray-1.13.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:554cda50101a14e1bca2453bd1013949cdc4ebcd4709065139955578f8b0c354"}, + {file = "memray-1.13.4-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:e3e261995acc40f8bd4a10740b25f37eccc3e413449ceb73263216ec3c6fee7b"}, + {file = "memray-1.13.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5e8ef7cc755a5a3a4b5d9991cf70428220e9138bc5967b5764b2fa7a1fb4d7a6"}, + {file = "memray-1.13.4-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7c8ea410c842a31ee07e76b409c273d23e0b670d166c2330488d1164ab42a4d1"}, + {file = "memray-1.13.4-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:22c9656c78a50b4569a8273d062cc6c139e9f7cfec3f793e60ef7e0cb46c2a76"}, + {file = "memray-1.13.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7096401ff3b7ce5f759e45bd71b0899ad50a607924ee23ad02423aa4fa505f52"}, + {file = "memray-1.13.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2072a454846e055d5833d17b1f5e6106ae18e425974c3968276a1952b0156f2b"}, + {file = "memray-1.13.4-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:f19fb4a20d796af869691531d2d6540d27bfbf0df9118bd17e547a23224a8b3e"}, + {file = "memray-1.13.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b1331de55aab1c409ec295b155770487004e0c6d08db0fe903e9377be978bacd"}, + {file = "memray-1.13.4-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f43bfa96114012d76025a0ee42206c7d914b6113c491dc221e1b7a901c51242a"}, + {file = "memray-1.13.4-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e0cc6299a09d3c51fd1a45bd816e9dd68a7092a3eaf62aeaa2ee01068f2a1d0b"}, + {file = "memray-1.13.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cbaa39bf7041e32282ad84a9fd9bd98622f78f649ccb7d1075382fed84e8125"}, + {file = "memray-1.13.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:59bba975fbbced85fe6f61685aef459777faf3b8a5b4f0de4fa5b99cf6f1a5e7"}, + {file = "memray-1.13.4.tar.gz", hash = "sha256:48f8f9b89b3a84028668244151eb7248189fb3f4f2a761ec1211439adcbb2ad1"}, ] [package.dependencies] @@ -543,43 +543,43 @@ test = ["Cython", "greenlet", "ipython", "pytest", "pytest-cov", "pytest-textual [[package]] name = "mypy" -version = "1.10.1" +version = "1.11.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e36f229acfe250dc660790840916eb49726c928e8ce10fbdf90715090fe4ae02"}, - {file = "mypy-1.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:51a46974340baaa4145363b9e051812a2446cf583dfaeba124af966fa44593f7"}, - {file = "mypy-1.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:901c89c2d67bba57aaaca91ccdb659aa3a312de67f23b9dfb059727cce2e2e0a"}, - {file = "mypy-1.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0cd62192a4a32b77ceb31272d9e74d23cd88c8060c34d1d3622db3267679a5d9"}, - {file = "mypy-1.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:a2cbc68cb9e943ac0814c13e2452d2046c2f2b23ff0278e26599224cf164e78d"}, - {file = "mypy-1.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bd6f629b67bb43dc0d9211ee98b96d8dabc97b1ad38b9b25f5e4c4d7569a0c6a"}, - {file = "mypy-1.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a1bbb3a6f5ff319d2b9d40b4080d46cd639abe3516d5a62c070cf0114a457d84"}, - {file = "mypy-1.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8edd4e9bbbc9d7b79502eb9592cab808585516ae1bcc1446eb9122656c6066f"}, - {file = "mypy-1.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6166a88b15f1759f94a46fa474c7b1b05d134b1b61fca627dd7335454cc9aa6b"}, - {file = "mypy-1.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:5bb9cd11c01c8606a9d0b83ffa91d0b236a0e91bc4126d9ba9ce62906ada868e"}, - {file = "mypy-1.10.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d8681909f7b44d0b7b86e653ca152d6dff0eb5eb41694e163c6092124f8246d7"}, - {file = "mypy-1.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:378c03f53f10bbdd55ca94e46ec3ba255279706a6aacaecac52ad248f98205d3"}, - {file = "mypy-1.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bacf8f3a3d7d849f40ca6caea5c055122efe70e81480c8328ad29c55c69e93e"}, - {file = "mypy-1.10.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:701b5f71413f1e9855566a34d6e9d12624e9e0a8818a5704d74d6b0402e66c04"}, - {file = "mypy-1.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:3c4c2992f6ea46ff7fce0072642cfb62af7a2484efe69017ed8b095f7b39ef31"}, - {file = "mypy-1.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:604282c886497645ffb87b8f35a57ec773a4a2721161e709a4422c1636ddde5c"}, - {file = "mypy-1.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37fd87cab83f09842653f08de066ee68f1182b9b5282e4634cdb4b407266bade"}, - {file = "mypy-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8addf6313777dbb92e9564c5d32ec122bf2c6c39d683ea64de6a1fd98b90fe37"}, - {file = "mypy-1.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5cc3ca0a244eb9a5249c7c583ad9a7e881aa5d7b73c35652296ddcdb33b2b9c7"}, - {file = "mypy-1.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:1b3a2ffce52cc4dbaeee4df762f20a2905aa171ef157b82192f2e2f368eec05d"}, - {file = "mypy-1.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fe85ed6836165d52ae8b88f99527d3d1b2362e0cb90b005409b8bed90e9059b3"}, - {file = "mypy-1.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c2ae450d60d7d020d67ab440c6e3fae375809988119817214440033f26ddf7bf"}, - {file = "mypy-1.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6be84c06e6abd72f960ba9a71561c14137a583093ffcf9bbfaf5e613d63fa531"}, - {file = "mypy-1.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2189ff1e39db399f08205e22a797383613ce1cb0cb3b13d8bcf0170e45b96cc3"}, - {file = "mypy-1.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:97a131ee36ac37ce9581f4220311247ab6cba896b4395b9c87af0675a13a755f"}, - {file = "mypy-1.10.1-py3-none-any.whl", hash = "sha256:71d8ac0b906354ebda8ef1673e5fde785936ac1f29ff6987c7483cfbd5a4235a"}, - {file = "mypy-1.10.1.tar.gz", hash = "sha256:1f8f492d7db9e3593ef42d4f115f04e556130f2819ad33ab84551403e97dd4c0"}, + {file = "mypy-1.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3824187c99b893f90c845bab405a585d1ced4ff55421fdf5c84cb7710995229"}, + {file = "mypy-1.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:96f8dbc2c85046c81bcddc246232d500ad729cb720da4e20fce3b542cab91287"}, + {file = "mypy-1.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a5d8d8dd8613a3e2be3eae829ee891b6b2de6302f24766ff06cb2875f5be9c6"}, + {file = "mypy-1.11.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:72596a79bbfb195fd41405cffa18210af3811beb91ff946dbcb7368240eed6be"}, + {file = "mypy-1.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:35ce88b8ed3a759634cb4eb646d002c4cef0a38f20565ee82b5023558eb90c00"}, + {file = "mypy-1.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:98790025861cb2c3db8c2f5ad10fc8c336ed2a55f4daf1b8b3f877826b6ff2eb"}, + {file = "mypy-1.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:25bcfa75b9b5a5f8d67147a54ea97ed63a653995a82798221cca2a315c0238c1"}, + {file = "mypy-1.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bea2a0e71c2a375c9fa0ede3d98324214d67b3cbbfcbd55ac8f750f85a414e3"}, + {file = "mypy-1.11.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2b3d36baac48e40e3064d2901f2fbd2a2d6880ec6ce6358825c85031d7c0d4d"}, + {file = "mypy-1.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:d8e2e43977f0e09f149ea69fd0556623919f816764e26d74da0c8a7b48f3e18a"}, + {file = "mypy-1.11.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1d44c1e44a8be986b54b09f15f2c1a66368eb43861b4e82573026e04c48a9e20"}, + {file = "mypy-1.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cea3d0fb69637944dd321f41bc896e11d0fb0b0aa531d887a6da70f6e7473aba"}, + {file = "mypy-1.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a83ec98ae12d51c252be61521aa5731f5512231d0b738b4cb2498344f0b840cd"}, + {file = "mypy-1.11.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c7b73a856522417beb78e0fb6d33ef89474e7a622db2653bc1285af36e2e3e3d"}, + {file = "mypy-1.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:f2268d9fcd9686b61ab64f077be7ffbc6fbcdfb4103e5dd0cc5eaab53a8886c2"}, + {file = "mypy-1.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:940bfff7283c267ae6522ef926a7887305945f716a7704d3344d6d07f02df850"}, + {file = "mypy-1.11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:14f9294528b5f5cf96c721f231c9f5b2733164e02c1c018ed1a0eff8a18005ac"}, + {file = "mypy-1.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7b54c27783991399046837df5c7c9d325d921394757d09dbcbf96aee4649fe9"}, + {file = "mypy-1.11.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:65f190a6349dec29c8d1a1cd4aa71284177aee5949e0502e6379b42873eddbe7"}, + {file = "mypy-1.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbe286303241fea8c2ea5466f6e0e6a046a135a7e7609167b07fd4e7baf151bf"}, + {file = "mypy-1.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:104e9c1620c2675420abd1f6c44bab7dd33cc85aea751c985006e83dcd001095"}, + {file = "mypy-1.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f006e955718ecd8d159cee9932b64fba8f86ee6f7728ca3ac66c3a54b0062abe"}, + {file = "mypy-1.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:becc9111ca572b04e7e77131bc708480cc88a911adf3d0239f974c034b78085c"}, + {file = "mypy-1.11.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6801319fe76c3f3a3833f2b5af7bd2c17bb93c00026a2a1b924e6762f5b19e13"}, + {file = "mypy-1.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:c1a184c64521dc549324ec6ef7cbaa6b351912be9cb5edb803c2808a0d7e85ac"}, + {file = "mypy-1.11.0-py3-none-any.whl", hash = "sha256:56913ec8c7638b0091ef4da6fcc9136896914a9d60d54670a75880c3e5b99ace"}, + {file = "mypy-1.11.0.tar.gz", hash = "sha256:93743608c7348772fdc717af4aeee1997293a1ad04bc0ea6efa15bf65385c538"}, ] [package.dependencies] mypy-extensions = ">=1.0.0" -typing-extensions = ">=4.1.0" +typing-extensions = ">=4.6.0" [package.extras] dmypy = ["psutil (>=4.0)"] @@ -850,13 +850,13 @@ test = ["assertpy (>=1.1)", "beautifulsoup4 (>=4.11.1)", "black (>=22.1.0)", "fl [[package]] name = "pytest-memray" -version = "1.6.0" +version = "1.7.0" description = "A simple plugin to use with pytest" optional = false python-versions = ">=3.8" files = [ - {file = "pytest_memray-1.6.0-py3-none-any.whl", hash = "sha256:267db3f9d3ad3e443c6743e5261ce64caff3e2e8d632850b58c0ae0925fed765"}, - {file = "pytest_memray-1.6.0.tar.gz", hash = "sha256:364152252afd563fc8b58459325f360030d2b0d5673896018a68badb35402339"}, + {file = "pytest_memray-1.7.0-py3-none-any.whl", hash = "sha256:b896718c1adf6d0cd339dfaaaa5620f035c9919e1199a79b3453804a1254306f"}, + {file = "pytest_memray-1.7.0.tar.gz", hash = "sha256:c18fa907d2210b42f4096c093e2d3416dfc002dcaa450ef3f9ba819bc3dd8f5f"}, ] [package.dependencies] @@ -866,7 +866,7 @@ pytest = ">=7.2" [package.extras] docs = ["furo (>=2022.12.7)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinx-inline-tabs (>=2022.1.2b11)", "sphinxcontrib-programoutput (>=0.17)", "towncrier (>=22.12)"] lint = ["black (==22.12)", "isort (==5.11.4)", "mypy (==0.991)", "ruff (==0.0.272)"] -test = ["covdefaults (>=2.2.2)", "coverage (>=7.0.5)", "flaky (>=3.7)", "pytest (>=7.2)", "pytest-xdist (>=3.1)"] +test = ["anyio (>=4.4.0)", "covdefaults (>=2.2.2)", "coverage (>=7.0.5)", "flaky (>=3.7)", "pytest (>=7.2)", "pytest-xdist (>=3.1)"] [[package]] name = "pytest-metadata" @@ -1033,18 +1033,19 @@ setuptools = "*" [[package]] name = "setuptools" -version = "70.3.0" +version = "71.1.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-70.3.0-py3-none-any.whl", hash = "sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc"}, - {file = "setuptools-70.3.0.tar.gz", hash = "sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5"}, + {file = "setuptools-71.1.0-py3-none-any.whl", hash = "sha256:33874fdc59b3188304b2e7c80d9029097ea31627180896fb549c578ceb8a0855"}, + {file = "setuptools-71.1.0.tar.gz", hash = "sha256:032d42ee9fb536e33087fb66cac5f840eb9391ed05637b3f2a76a7c8fb477936"}, ] [package.extras] +core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "six" @@ -1059,13 +1060,13 @@ files = [ [[package]] name = "textual" -version = "0.72.0" +version = "0.74.0" description = "Modern Text User Interface framework" optional = false -python-versions = "<4.0,>=3.8" +python-versions = "<4.0.0,>=3.8.1" files = [ - {file = "textual-0.72.0-py3-none-any.whl", hash = "sha256:a9886eb96bd6391b8795244d2b8fe592204556c42264ea7513a1211584e17366"}, - {file = "textual-0.72.0.tar.gz", hash = "sha256:14174ce8d49016a85aa6c0669d0881b5419e98cf46d429f263314295409ed262"}, + {file = "textual-0.74.0-py3-none-any.whl", hash = "sha256:69b18904d11400e586274deb1270f5db7b4254a2ac00fe805f23b16c324345e4"}, + {file = "textual-0.74.0.tar.gz", hash = "sha256:808c4e8727283ef84a123620449b217b6033ffde49f3ed195b3d0f98bb042969"}, ] [package.dependencies] diff --git a/tests/test_reason.py b/tests/test_reason.py index 314c3a8..ec51a21 100644 --- a/tests/test_reason.py +++ b/tests/test_reason.py @@ -88,9 +88,7 @@ def test_reasoner(reasoner: str, err_list: list) -> list: def test_validate(errors: str) -> str: result = ValidatePlugin( ontology_graph_iri=VALIDATE_ONTOLOGY_GRAPH_IRI, - produce_graph=True, output_graph_iri=OUTPUT_GRAPH_IRI, - write_md=True, validate_profile=True, md_filename=MD_FILENAME, ).execute((), context=TestExecutionContext(PROJECT_ID)) From 79e936657c79c4cd1f991905bf2b77a2f0b4e27d Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Thu, 25 Jul 2024 16:02:25 +0100 Subject: [PATCH 02/32] fix condition to write MD file to project --- cmem_plugin_reason/plugin_validate.py | 10 +++++++--- cmem_plugin_reason/utils.py | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index 55ac901..5559b73 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -111,7 +111,12 @@ def __init__( # noqa: PLR0913 self.reasoner = reasoner self.output_graph_iri = output_graph_iri self.stop_at_inconsistencies = stop_at_inconsistencies - self.md_filename = md_filename if md_filename else "mdfile.md" + if md_filename: + self.md_filename = md_filename + self.write_md = True + else: + self.md_filename = "mdfile.md" + self.write_md = False self.validate_profile = validate_profile self.max_ram_percentage = max_ram_percentage @@ -218,8 +223,7 @@ def _execute(self, context: ExecutionContext) -> Entities: self.add_profiles(validate_profiles(self, graphs)) if self.validate_profile else [] ) - # if self.write_md: - if self.md_filename: + if self.write_md: setup_cmempy_user_access(context.user) self.make_resource(context) diff --git a/cmem_plugin_reason/utils.py b/cmem_plugin_reason/utils.py index 94dcef4..37c4fe6 100644 --- a/cmem_plugin_reason/utils.py +++ b/cmem_plugin_reason/utils.py @@ -198,7 +198,7 @@ def get_provenance(plugin: WorkflowPlugin, context: ExecutionContext) -> dict | def robot(cmd: str, max_ram_percentage: int) -> CompletedProcess: """Run robot.jar""" jar = Path(__path__[0]) / "bin" / "robot.jar" - cmd = f"java -XX:MaxRAMPercentage={max_ram_percentage} -jar {jar} " + cmd + cmd = f"java -XX:MaxRAMPercentage={max_ram_percentage} -jar {jar} {cmd}" return run(shlex.split(cmd), check=False, capture_output=True) # noqa: S603 From 70e4ce593e4b9f16c5ad4e58eafef82dc463c6eb Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Thu, 25 Jul 2024 19:34:11 +0100 Subject: [PATCH 03/32] validate inputs (Reason) --- cmem_plugin_reason/plugin_reason.py | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index ad4ef8f..c056d16 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -333,27 +333,13 @@ def post_valid_profiles(self, inputs: Sequence[Entities], graphs: dict) -> None: if self.input_profiles: values = next(inputs[0].entities).values paths = [p.path for p in inputs[0].schema.paths] - validated_ontology = values[paths.index("ontology")][0] valid_profiles = values[paths.index("profile")] - if validated_ontology != self.ontology_graph_iri: - raise ValueError( - "The ontology IRI validated with Validate differs from the input ontology IRI." - ) else: valid_profiles = validate_profiles(self, graphs) post_profiles(self, valid_profiles) def _execute(self, inputs: Sequence[Entities], context: ExecutionContext) -> None: """`Execute plugin""" - if self.input_profiles: - if not inputs: - raise OSError( - 'Input entities needed if "Process valid OWL profiles from input" is enabled' - ) - paths = [p.path for p in inputs[0].schema.paths] - if "profile" not in paths or "ontology" not in paths: - raise ValueError("Invalid input for processing OWL profiles") - setup_cmempy_user_access(context.user) graphs = get_graphs_tree((self.data_graph_iri, self.ontology_graph_iri)) self.get_graphs(graphs, context) @@ -366,6 +352,19 @@ def _execute(self, inputs: Sequence[Entities], context: ExecutionContext) -> Non post_provenance(self, get_provenance(self, context)) def execute(self, inputs: Sequence[Entities], context: ExecutionContext) -> None: - """Remove temp files on error""" + """Validate input, execute plugin with temporary directory""" + if self.input_profiles: + values = next(inputs[0].entities).values + paths = [p.path for p in inputs[0].schema.paths] + if not inputs: + raise OSError( + 'Input entities needed if "Process valid OWL profiles from input" is enabled' + ) + if "profile" not in paths or "ontology" not in paths: + raise ValueError("Invalid input for processing OWL profiles") + if values[paths.index("ontology")][0] != self.ontology_graph_iri: + raise ValueError( + "The ontology IRI validated with Validate differs from the input ontology IRI." + ) with TemporaryDirectory() as self.temp: self._execute(inputs, context) From d6735f07a2c277b36ec2e6512f3d94eac961a941 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Fri, 26 Jul 2024 08:46:55 +0100 Subject: [PATCH 04/32] use ontology IRI from input if input_profiles=True --- cmem_plugin_reason/plugin_reason.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index c056d16..930eb00 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -270,7 +270,7 @@ def __init__( # noqa: PLR0913, C901 self.input_ports = FixedNumberOfInputs([FixedSchemaPort(self.generate_input_schema())]) else: self.input_ports = FixedNumberOfInputs([]) - self.output_port = FixedSchemaPort(EntitySchema(type_uri="", paths=[])) + self.output_port = None def generate_input_schema(self) -> EntitySchema: """Generate the output schema.""" @@ -354,17 +354,26 @@ def _execute(self, inputs: Sequence[Entities], context: ExecutionContext) -> Non def execute(self, inputs: Sequence[Entities], context: ExecutionContext) -> None: """Validate input, execute plugin with temporary directory""" if self.input_profiles: + errors = "" values = next(inputs[0].entities).values paths = [p.path for p in inputs[0].schema.paths] if not inputs: raise OSError( 'Input entities needed if "Process valid OWL profiles from input" is enabled' ) - if "profile" not in paths or "ontology" not in paths: - raise ValueError("Invalid input for processing OWL profiles") - if values[paths.index("ontology")][0] != self.ontology_graph_iri: - raise ValueError( - "The ontology IRI validated with Validate differs from the input ontology IRI." - ) + if "profile" not in paths: + errors += 'No value for "profile" given on input. ' + if "ontology" not in paths: + errors += 'No value for "ontology" given on input. ' + self.ontology_graph_iri = values[paths.index("ontology")][0] + if not validators.url(self.ontology_graph_iri): + errors += 'Invalid IRI for parameter "Ontology graph IRI". ' + if self.ontology_graph_iri == self.data_graph_iri: + errors += "Ontology graph IRI cannot be the same as the data graph IRI. " + if self.ontology_graph_iri == self.output_graph_iri: + errors += "Ontology graph IRI cannot be the same as the output graph IRI. " + if errors: + raise ValueError(errors[:-1]) + with TemporaryDirectory() as self.temp: self._execute(inputs, context) From c351fa709f9810710b6ffb8413f860a240e55f57 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Fri, 26 Jul 2024 10:39:21 +0100 Subject: [PATCH 05/32] fix incorrect stopping of workflow if 'validate_profiles' is enabled in Validate --- cmem_plugin_reason/plugin_reason.py | 6 +++--- cmem_plugin_reason/plugin_validate.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index 930eb00..e038815 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -174,9 +174,9 @@ param_type=BoolParameterType(), name="input_profiles", label="Process valid OWL profiles from input", - description="""If the "validate OWL profiles" parameter is enabled, take values from the - input (paths "profile" and "ontology") instead of running the validation in the plugin. - """, + description="""If the "validate OWL profiles" parameter is enabled, the valid profiles + and ontology IRI is taken from the input (paths "profile" and "ontology") instead of + running the validation in the plugin.""", default_value=False, advanced=True, ), diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index 5559b73..4d375dc 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -203,7 +203,7 @@ def make_entities(self, text: str, valid_profiles: list) -> Entities: values=values, ), ] - return Entities(entities=entities, schema=self.schema) + return Entities(entities=iter(entities), schema=self.schema) def _execute(self, context: ExecutionContext) -> Entities: """Run the workflow operator.""" @@ -229,7 +229,7 @@ def _execute(self, context: ExecutionContext) -> Entities: text = (Path(self.temp) / self.md_filename).read_text() - if self.stop_at_inconsistencies and text != "No explanations found.": + if self.stop_at_inconsistencies and text.split("\n", 1)[0] != "No explanations found.": raise RuntimeError("Inconsistencies found in Ontology.") return self.make_entities(text, valid_profiles) From fe56b9549018fa6d2bc73d0efcd7fa3c1dfa475f Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Fri, 26 Jul 2024 10:48:37 +0100 Subject: [PATCH 06/32] remove iter cast from output entities --- cmem_plugin_reason/plugin_validate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index 4d375dc..a2ba36b 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -203,7 +203,7 @@ def make_entities(self, text: str, valid_profiles: list) -> Entities: values=values, ), ] - return Entities(entities=iter(entities), schema=self.schema) + return Entities(entities=entities, schema=self.schema) def _execute(self, context: ExecutionContext) -> Entities: """Run the workflow operator.""" From 4d8136700fcc45ef04b0c30d89a08c20c5f15d88 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Fri, 26 Jul 2024 17:26:23 +0100 Subject: [PATCH 07/32] fixing import bug --- CHANGELOG.md | 7 ++++++- cmem_plugin_reason/plugin_reason.py | 17 ++++++++++++++++- cmem_plugin_reason/plugin_validate.py | 2 +- cmem_plugin_reason/utils.py | 6 +++--- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59ef909..9dee8a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,15 +6,20 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ## [Unreleased] - ### Added - defined input and output schema +### Fixed + + - incorrect stopping of workflow if "validate_profiles" and "stop_at_inconsistencies" is enabled in Validate plugin + ### Changed - raise OSError on post result graph error - removed write_md and produce_graph bool parameters +- if "input_profiles" is enabled the Reason plugin expects ontology_iri and "profile" non the input. +The ontologi iri on the input overrides the plugin setting. ## [1.0.0beta4] 2024-07-12 diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index e038815..e7ff194 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -294,12 +294,25 @@ def get_graphs(self, graphs: dict, context: ExecutionContext) -> None: def reason(self, graphs: dict) -> None: """Reason""" + # remove_query = f""" + # SELECT ?s ?p ?o + # WHERE {{ + # ?s <{self.output_graph_iri}> . + # }} + # """ + # filtered_file = Path(self.temp) / "filtered_triples.owl" + # query_file = Path(self.temp) / "remove.rq" + # with query_file.open("w") as rqfile: + # rqfile.write(remove_query) + axioms = " ".join(k for k, v in self.axioms.items() if v) data_location = f"{self.temp}/{graphs[self.data_graph_iri]}" utctime = str(datetime.fromtimestamp(int(time()), tz=UTC))[:-6].replace(" ", "T") + "Z" cmd = ( f'merge --input "{data_location}" ' "--collapse-import-closure false " + # f'--query query.sparql {filtered_file} ' + # f'remove --input "{data_location}" --input {filtered_file} --select "triples" ' f"reason --reasoner {self.reasoner} " f'--axiom-generators "{axioms}" ' f"--include-indirect true " @@ -341,7 +354,9 @@ def post_valid_profiles(self, inputs: Sequence[Entities], graphs: dict) -> None: def _execute(self, inputs: Sequence[Entities], context: ExecutionContext) -> None: """`Execute plugin""" setup_cmempy_user_access(context.user) - graphs = get_graphs_tree((self.data_graph_iri, self.ontology_graph_iri)) + graphs = get_graphs_tree( + (self.data_graph_iri, self.ontology_graph_iri, self.output_graph_iri) + ) self.get_graphs(graphs, context) create_xml_catalog_file(self.temp, graphs) self.reason(graphs) diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index a2ba36b..8fadaf9 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -208,7 +208,7 @@ def make_entities(self, text: str, valid_profiles: list) -> Entities: def _execute(self, context: ExecutionContext) -> Entities: """Run the workflow operator.""" setup_cmempy_user_access(context.user) - graphs = get_graphs_tree((self.ontology_graph_iri,)) + graphs = get_graphs_tree((self.ontology_graph_iri, self.output_graph_iri)) self.get_graphs(graphs, context) create_xml_catalog_file(self.temp, graphs) self.explain(graphs) diff --git a/cmem_plugin_reason/utils.py b/cmem_plugin_reason/utils.py index 37c4fe6..1e49cab 100644 --- a/cmem_plugin_reason/utils.py +++ b/cmem_plugin_reason/utils.py @@ -86,15 +86,15 @@ def create_xml_catalog_file(dir_: str, graphs: dict) -> None: def get_graphs_tree(graph_iris: tuple) -> dict: - """Get graph import tree""" + """Get graph import tree. Last item in tuple is output_graph_iri which is excluded""" graphs = {} - for graph_iri in graph_iris: + for graph_iri in graph_iris[:-1]: if graph_iri not in graphs: graphs[graph_iri] = f"{token_hex(8)}.nt" tree = get_graph_import_tree(graph_iri) for value in tree["tree"].values(): for iri in value: - if iri not in graphs: + if iri not in graphs and iri != graph_iri[-1]: graphs[iri] = f"{token_hex(8)}.nt" return graphs From e2aad789c36e77c591bc3b41b7a9566a74f64f20 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Wed, 7 Aug 2024 11:37:53 +0100 Subject: [PATCH 08/32] fix error when result graph is imported in input graph --- CHANGELOG.md | 5 +- cmem_plugin_reason/plugin_reason.py | 24 ++-- poetry.lock | 200 +++++++++++++++------------- 3 files changed, 121 insertions(+), 108 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dee8a8..3d6755b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,13 +13,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ### Fixed - incorrect stopping of workflow if "validate_profiles" and "stop_at_inconsistencies" is enabled in Validate plugin + - fixed error when output graph is imported by input graph; the import is removed in-memory before reasoning ### Changed - raise OSError on post result graph error - removed write_md and produce_graph bool parameters -- if "input_profiles" is enabled the Reason plugin expects ontology_iri and "profile" non the input. -The ontologi iri on the input overrides the plugin setting. +- if "input_profiles" is enabled the Reason plugin expects "ontology_iri" and "profile" on the input. +The ontology IRI on the input overrides the plugin setting. ## [1.0.0beta4] 2024-07-12 diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index e7ff194..b037fb0 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -285,34 +285,26 @@ def get_graphs(self, graphs: dict, context: ExecutionContext) -> None: self.log.info(f"Fetching graph {graph}.") with (Path(self.temp) / graphs[graph]).open("w", encoding="utf-8") as file: setup_cmempy_user_access(context.user) - file.write(get(graph).text) + for line in get(graph).text.splitlines(): + if line != ( + f"<{graph}> " + f"<{self.output_graph_iri}> ." + ): + file.write(line + "\n") if graph == self.data_graph_iri: file.write( - f"\n<{graph}> " - f" <{self.ontology_graph_iri}> ." + f"<{graph}> " + f"<{self.ontology_graph_iri}> ." ) def reason(self, graphs: dict) -> None: """Reason""" - # remove_query = f""" - # SELECT ?s ?p ?o - # WHERE {{ - # ?s <{self.output_graph_iri}> . - # }} - # """ - # filtered_file = Path(self.temp) / "filtered_triples.owl" - # query_file = Path(self.temp) / "remove.rq" - # with query_file.open("w") as rqfile: - # rqfile.write(remove_query) - axioms = " ".join(k for k, v in self.axioms.items() if v) data_location = f"{self.temp}/{graphs[self.data_graph_iri]}" utctime = str(datetime.fromtimestamp(int(time()), tz=UTC))[:-6].replace(" ", "T") + "Z" cmd = ( f'merge --input "{data_location}" ' "--collapse-import-closure false " - # f'--query query.sparql {filtered_file} ' - # f'remove --input "{data_location}" --input {filtered_file} --select "triples" ' f"reason --reasoner {self.reasoner} " f'--axiom-generators "{axioms}" ' f"--include-indirect true " diff --git a/poetry.lock b/poetry.lock index c47eca0..627c38f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -170,63 +170,83 @@ files = [ [[package]] name = "coverage" -version = "7.6.0" +version = "7.6.1" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dff044f661f59dace805eedb4a7404c573b6ff0cdba4a524141bc63d7be5c7fd"}, - {file = "coverage-7.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8659fd33ee9e6ca03950cfdcdf271d645cf681609153f218826dd9805ab585c"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7792f0ab20df8071d669d929c75c97fecfa6bcab82c10ee4adb91c7a54055463"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4b3cd1ca7cd73d229487fa5caca9e4bc1f0bca96526b922d61053ea751fe791"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7e128f85c0b419907d1f38e616c4f1e9f1d1b37a7949f44df9a73d5da5cd53c"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a94925102c89247530ae1dab7dc02c690942566f22e189cbd53579b0693c0783"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dcd070b5b585b50e6617e8972f3fbbee786afca71b1936ac06257f7e178f00f6"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d50a252b23b9b4dfeefc1f663c568a221092cbaded20a05a11665d0dbec9b8fb"}, - {file = "coverage-7.6.0-cp310-cp310-win32.whl", hash = "sha256:0e7b27d04131c46e6894f23a4ae186a6a2207209a05df5b6ad4caee6d54a222c"}, - {file = "coverage-7.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:54dece71673b3187c86226c3ca793c5f891f9fc3d8aa183f2e3653da18566169"}, - {file = "coverage-7.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7b525ab52ce18c57ae232ba6f7010297a87ced82a2383b1afd238849c1ff933"}, - {file = "coverage-7.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bea27c4269234e06f621f3fac3925f56ff34bc14521484b8f66a580aacc2e7d"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed8d1d1821ba5fc88d4a4f45387b65de52382fa3ef1f0115a4f7a20cdfab0e94"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01c322ef2bbe15057bc4bf132b525b7e3f7206f071799eb8aa6ad1940bcf5fb1"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03cafe82c1b32b770a29fd6de923625ccac3185a54a5e66606da26d105f37dac"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0d1b923fc4a40c5832be4f35a5dab0e5ff89cddf83bb4174499e02ea089daf57"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4b03741e70fb811d1a9a1d75355cf391f274ed85847f4b78e35459899f57af4d"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a73d18625f6a8a1cbb11eadc1d03929f9510f4131879288e3f7922097a429f63"}, - {file = "coverage-7.6.0-cp311-cp311-win32.whl", hash = "sha256:65fa405b837060db569a61ec368b74688f429b32fa47a8929a7a2f9b47183713"}, - {file = "coverage-7.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:6379688fb4cfa921ae349c76eb1a9ab26b65f32b03d46bb0eed841fd4cb6afb1"}, - {file = "coverage-7.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f7db0b6ae1f96ae41afe626095149ecd1b212b424626175a6633c2999eaad45b"}, - {file = "coverage-7.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bbdf9a72403110a3bdae77948b8011f644571311c2fb35ee15f0f10a8fc082e8"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc44bf0315268e253bf563f3560e6c004efe38f76db03a1558274a6e04bf5d5"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da8549d17489cd52f85a9829d0e1d91059359b3c54a26f28bec2c5d369524807"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0086cd4fc71b7d485ac93ca4239c8f75732c2ae3ba83f6be1c9be59d9e2c6382"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1fad32ee9b27350687035cb5fdf9145bc9cf0a094a9577d43e909948ebcfa27b"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:044a0985a4f25b335882b0966625270a8d9db3d3409ddc49a4eb00b0ef5e8cee"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:76d5f82213aa78098b9b964ea89de4617e70e0d43e97900c2778a50856dac605"}, - {file = "coverage-7.6.0-cp312-cp312-win32.whl", hash = "sha256:3c59105f8d58ce500f348c5b56163a4113a440dad6daa2294b5052a10db866da"}, - {file = "coverage-7.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:ca5d79cfdae420a1d52bf177de4bc2289c321d6c961ae321503b2ca59c17ae67"}, - {file = "coverage-7.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d39bd10f0ae453554798b125d2f39884290c480f56e8a02ba7a6ed552005243b"}, - {file = "coverage-7.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:beb08e8508e53a568811016e59f3234d29c2583f6b6e28572f0954a6b4f7e03d"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2e16f4cd2bc4d88ba30ca2d3bbf2f21f00f382cf4e1ce3b1ddc96c634bc48ca"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6616d1c9bf1e3faea78711ee42a8b972367d82ceae233ec0ac61cc7fec09fa6b"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad4567d6c334c46046d1c4c20024de2a1c3abc626817ae21ae3da600f5779b44"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d17c6a415d68cfe1091d3296ba5749d3d8696e42c37fca5d4860c5bf7b729f03"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9146579352d7b5f6412735d0f203bbd8d00113a680b66565e205bc605ef81bc6"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cdab02a0a941af190df8782aafc591ef3ad08824f97850b015c8c6a8b3877b0b"}, - {file = "coverage-7.6.0-cp38-cp38-win32.whl", hash = "sha256:df423f351b162a702c053d5dddc0fc0ef9a9e27ea3f449781ace5f906b664428"}, - {file = "coverage-7.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:f2501d60d7497fd55e391f423f965bbe9e650e9ffc3c627d5f0ac516026000b8"}, - {file = "coverage-7.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7221f9ac9dad9492cecab6f676b3eaf9185141539d5c9689d13fd6b0d7de840c"}, - {file = "coverage-7.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ddaaa91bfc4477d2871442bbf30a125e8fe6b05da8a0015507bfbf4718228ab2"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4cbe651f3904e28f3a55d6f371203049034b4ddbce65a54527a3f189ca3b390"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:831b476d79408ab6ccfadaaf199906c833f02fdb32c9ab907b1d4aa0713cfa3b"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46c3d091059ad0b9c59d1034de74a7f36dcfa7f6d3bde782c49deb42438f2450"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4d5fae0a22dc86259dee66f2cc6c1d3e490c4a1214d7daa2a93d07491c5c04b6"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:07ed352205574aad067482e53dd606926afebcb5590653121063fbf4e2175166"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:49c76cdfa13015c4560702574bad67f0e15ca5a2872c6a125f6327ead2b731dd"}, - {file = "coverage-7.6.0-cp39-cp39-win32.whl", hash = "sha256:482855914928c8175735a2a59c8dc5806cf7d8f032e4820d52e845d1f731dca2"}, - {file = "coverage-7.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:543ef9179bc55edfd895154a51792b01c017c87af0ebaae092720152e19e42ca"}, - {file = "coverage-7.6.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:6fe885135c8a479d3e37a7aae61cbd3a0fb2deccb4dda3c25f92a49189f766d6"}, - {file = "coverage-7.6.0.tar.gz", hash = "sha256:289cc803fa1dc901f84701ac10c9ee873619320f2f9aff38794db4a4a0268d51"}, + {file = "coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16"}, + {file = "coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959"}, + {file = "coverage-7.6.1-cp310-cp310-win32.whl", hash = "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232"}, + {file = "coverage-7.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0"}, + {file = "coverage-7.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93"}, + {file = "coverage-7.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133"}, + {file = "coverage-7.6.1-cp311-cp311-win32.whl", hash = "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c"}, + {file = "coverage-7.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6"}, + {file = "coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778"}, + {file = "coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d"}, + {file = "coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5"}, + {file = "coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb"}, + {file = "coverage-7.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106"}, + {file = "coverage-7.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155"}, + {file = "coverage-7.6.1-cp313-cp313-win32.whl", hash = "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a"}, + {file = "coverage-7.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129"}, + {file = "coverage-7.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e"}, + {file = "coverage-7.6.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3"}, + {file = "coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f"}, + {file = "coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657"}, + {file = "coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0"}, + {file = "coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989"}, + {file = "coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7"}, + {file = "coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8"}, + {file = "coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255"}, + {file = "coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36"}, + {file = "coverage-7.6.1-cp39-cp39-win32.whl", hash = "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c"}, + {file = "coverage-7.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca"}, + {file = "coverage-7.6.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df"}, + {file = "coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d"}, ] [package.extras] @@ -543,38 +563,38 @@ test = ["Cython", "greenlet", "ipython", "pytest", "pytest-cov", "pytest-textual [[package]] name = "mypy" -version = "1.11.0" +version = "1.11.1" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3824187c99b893f90c845bab405a585d1ced4ff55421fdf5c84cb7710995229"}, - {file = "mypy-1.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:96f8dbc2c85046c81bcddc246232d500ad729cb720da4e20fce3b542cab91287"}, - {file = "mypy-1.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a5d8d8dd8613a3e2be3eae829ee891b6b2de6302f24766ff06cb2875f5be9c6"}, - {file = "mypy-1.11.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:72596a79bbfb195fd41405cffa18210af3811beb91ff946dbcb7368240eed6be"}, - {file = "mypy-1.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:35ce88b8ed3a759634cb4eb646d002c4cef0a38f20565ee82b5023558eb90c00"}, - {file = "mypy-1.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:98790025861cb2c3db8c2f5ad10fc8c336ed2a55f4daf1b8b3f877826b6ff2eb"}, - {file = "mypy-1.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:25bcfa75b9b5a5f8d67147a54ea97ed63a653995a82798221cca2a315c0238c1"}, - {file = "mypy-1.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bea2a0e71c2a375c9fa0ede3d98324214d67b3cbbfcbd55ac8f750f85a414e3"}, - {file = "mypy-1.11.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2b3d36baac48e40e3064d2901f2fbd2a2d6880ec6ce6358825c85031d7c0d4d"}, - {file = "mypy-1.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:d8e2e43977f0e09f149ea69fd0556623919f816764e26d74da0c8a7b48f3e18a"}, - {file = "mypy-1.11.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1d44c1e44a8be986b54b09f15f2c1a66368eb43861b4e82573026e04c48a9e20"}, - {file = "mypy-1.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cea3d0fb69637944dd321f41bc896e11d0fb0b0aa531d887a6da70f6e7473aba"}, - {file = "mypy-1.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a83ec98ae12d51c252be61521aa5731f5512231d0b738b4cb2498344f0b840cd"}, - {file = "mypy-1.11.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c7b73a856522417beb78e0fb6d33ef89474e7a622db2653bc1285af36e2e3e3d"}, - {file = "mypy-1.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:f2268d9fcd9686b61ab64f077be7ffbc6fbcdfb4103e5dd0cc5eaab53a8886c2"}, - {file = "mypy-1.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:940bfff7283c267ae6522ef926a7887305945f716a7704d3344d6d07f02df850"}, - {file = "mypy-1.11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:14f9294528b5f5cf96c721f231c9f5b2733164e02c1c018ed1a0eff8a18005ac"}, - {file = "mypy-1.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7b54c27783991399046837df5c7c9d325d921394757d09dbcbf96aee4649fe9"}, - {file = "mypy-1.11.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:65f190a6349dec29c8d1a1cd4aa71284177aee5949e0502e6379b42873eddbe7"}, - {file = "mypy-1.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbe286303241fea8c2ea5466f6e0e6a046a135a7e7609167b07fd4e7baf151bf"}, - {file = "mypy-1.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:104e9c1620c2675420abd1f6c44bab7dd33cc85aea751c985006e83dcd001095"}, - {file = "mypy-1.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f006e955718ecd8d159cee9932b64fba8f86ee6f7728ca3ac66c3a54b0062abe"}, - {file = "mypy-1.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:becc9111ca572b04e7e77131bc708480cc88a911adf3d0239f974c034b78085c"}, - {file = "mypy-1.11.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6801319fe76c3f3a3833f2b5af7bd2c17bb93c00026a2a1b924e6762f5b19e13"}, - {file = "mypy-1.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:c1a184c64521dc549324ec6ef7cbaa6b351912be9cb5edb803c2808a0d7e85ac"}, - {file = "mypy-1.11.0-py3-none-any.whl", hash = "sha256:56913ec8c7638b0091ef4da6fcc9136896914a9d60d54670a75880c3e5b99ace"}, - {file = "mypy-1.11.0.tar.gz", hash = "sha256:93743608c7348772fdc717af4aeee1997293a1ad04bc0ea6efa15bf65385c538"}, + {file = "mypy-1.11.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a32fc80b63de4b5b3e65f4be82b4cfa362a46702672aa6a0f443b4689af7008c"}, + {file = "mypy-1.11.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c1952f5ea8a5a959b05ed5f16452fddadbaae48b5d39235ab4c3fc444d5fd411"}, + {file = "mypy-1.11.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1e30dc3bfa4e157e53c1d17a0dad20f89dc433393e7702b813c10e200843b03"}, + {file = "mypy-1.11.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2c63350af88f43a66d3dfeeeb8d77af34a4f07d760b9eb3a8697f0386c7590b4"}, + {file = "mypy-1.11.1-cp310-cp310-win_amd64.whl", hash = "sha256:a831671bad47186603872a3abc19634f3011d7f83b083762c942442d51c58d58"}, + {file = "mypy-1.11.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7b6343d338390bb946d449677726edf60102a1c96079b4f002dedff375953fc5"}, + {file = "mypy-1.11.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e4fe9f4e5e521b458d8feb52547f4bade7ef8c93238dfb5bbc790d9ff2d770ca"}, + {file = "mypy-1.11.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:886c9dbecc87b9516eff294541bf7f3655722bf22bb898ee06985cd7269898de"}, + {file = "mypy-1.11.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fca4a60e1dd9fd0193ae0067eaeeb962f2d79e0d9f0f66223a0682f26ffcc809"}, + {file = "mypy-1.11.1-cp311-cp311-win_amd64.whl", hash = "sha256:0bd53faf56de9643336aeea1c925012837432b5faf1701ccca7fde70166ccf72"}, + {file = "mypy-1.11.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f39918a50f74dc5969807dcfaecafa804fa7f90c9d60506835036cc1bc891dc8"}, + {file = "mypy-1.11.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0bc71d1fb27a428139dd78621953effe0d208aed9857cb08d002280b0422003a"}, + {file = "mypy-1.11.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b868d3bcff720dd7217c383474008ddabaf048fad8d78ed948bb4b624870a417"}, + {file = "mypy-1.11.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a707ec1527ffcdd1c784d0924bf5cb15cd7f22683b919668a04d2b9c34549d2e"}, + {file = "mypy-1.11.1-cp312-cp312-win_amd64.whl", hash = "sha256:64f4a90e3ea07f590c5bcf9029035cf0efeae5ba8be511a8caada1a4893f5525"}, + {file = "mypy-1.11.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:749fd3213916f1751fff995fccf20c6195cae941dc968f3aaadf9bb4e430e5a2"}, + {file = "mypy-1.11.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b639dce63a0b19085213ec5fdd8cffd1d81988f47a2dec7100e93564f3e8fb3b"}, + {file = "mypy-1.11.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c956b49c5d865394d62941b109728c5c596a415e9c5b2be663dd26a1ff07bc0"}, + {file = "mypy-1.11.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45df906e8b6804ef4b666af29a87ad9f5921aad091c79cc38e12198e220beabd"}, + {file = "mypy-1.11.1-cp38-cp38-win_amd64.whl", hash = "sha256:d44be7551689d9d47b7abc27c71257adfdb53f03880841a5db15ddb22dc63edb"}, + {file = "mypy-1.11.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2684d3f693073ab89d76da8e3921883019ea8a3ec20fa5d8ecca6a2db4c54bbe"}, + {file = "mypy-1.11.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:79c07eb282cb457473add5052b63925e5cc97dfab9812ee65a7c7ab5e3cb551c"}, + {file = "mypy-1.11.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11965c2f571ded6239977b14deebd3f4c3abd9a92398712d6da3a772974fad69"}, + {file = "mypy-1.11.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a2b43895a0f8154df6519706d9bca8280cda52d3d9d1514b2d9c3e26792a0b74"}, + {file = "mypy-1.11.1-cp39-cp39-win_amd64.whl", hash = "sha256:1a81cf05975fd61aec5ae16501a091cfb9f605dc3e3c878c0da32f250b74760b"}, + {file = "mypy-1.11.1-py3-none-any.whl", hash = "sha256:0624bdb940255d2dd24e829d99a13cfeb72e4e9031f9492148f410ed30bcab54"}, + {file = "mypy-1.11.1.tar.gz", hash = "sha256:f404a0b069709f18bbdb702eb3dcfe51910602995de00bd39cea3050b5772d08"}, ] [package.dependencies] @@ -723,13 +743,13 @@ xmp = ["defusedxml"] [[package]] name = "pip" -version = "24.1.2" +version = "24.2" description = "The PyPA recommended tool for installing Python packages." optional = false python-versions = ">=3.8" files = [ - {file = "pip-24.1.2-py3-none-any.whl", hash = "sha256:7cd207eed4c60b0f411b444cd1464198fe186671c323b6cd6d433ed80fc9d247"}, - {file = "pip-24.1.2.tar.gz", hash = "sha256:e5458a0b89f2755e0ee8c0c77613fe5273e05f337907874d64f13171a898a7ff"}, + {file = "pip-24.2-py3-none-any.whl", hash = "sha256:2cd581cf58ab7fcfca4ce8efa6dcacd0de5bf8d0a3eb9ec927e07405f4d9e2a2"}, + {file = "pip-24.2.tar.gz", hash = "sha256:5b5e490b5e9cb275c879595064adce9ebd31b854e3e803740b72f9ccf34a45b8"}, ] [[package]] @@ -1033,13 +1053,13 @@ setuptools = "*" [[package]] name = "setuptools" -version = "71.1.0" +version = "72.1.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-71.1.0-py3-none-any.whl", hash = "sha256:33874fdc59b3188304b2e7c80d9029097ea31627180896fb549c578ceb8a0855"}, - {file = "setuptools-71.1.0.tar.gz", hash = "sha256:032d42ee9fb536e33087fb66cac5f840eb9391ed05637b3f2a76a7c8fb477936"}, + {file = "setuptools-72.1.0-py3-none-any.whl", hash = "sha256:5a03e1860cf56bb6ef48ce186b0e557fdba433237481a9a625176c2831be15d1"}, + {file = "setuptools-72.1.0.tar.gz", hash = "sha256:8d243eff56d095e5817f796ede6ae32941278f542e0f941867cc05ae52b162ec"}, ] [package.extras] @@ -1060,13 +1080,13 @@ files = [ [[package]] name = "textual" -version = "0.74.0" +version = "0.75.1" description = "Modern Text User Interface framework" optional = false python-versions = "<4.0.0,>=3.8.1" files = [ - {file = "textual-0.74.0-py3-none-any.whl", hash = "sha256:69b18904d11400e586274deb1270f5db7b4254a2ac00fe805f23b16c324345e4"}, - {file = "textual-0.74.0.tar.gz", hash = "sha256:808c4e8727283ef84a123620449b217b6033ffde49f3ed195b3d0f98bb042969"}, + {file = "textual-0.75.1-py3-none-any.whl", hash = "sha256:7edb1196753feae79890daa2287bc3180ebba2cbf63f59f2a160991325b020f2"}, + {file = "textual-0.75.1.tar.gz", hash = "sha256:3f0b53fe6119aa64853c7e60ced4d4e16fb23c83dee1e0fd19eddb3f2639c02e"}, ] [package.dependencies] From 43a3264f092092bf2ef0d4017966607703393e92 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Wed, 7 Aug 2024 14:39:03 +0100 Subject: [PATCH 09/32] edit readme --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 15285c3..a445a73 100644 --- a/README.md +++ b/README.md @@ -90,8 +90,9 @@ Validate the input ontology against OWL profiles (DL, EL, QL, RL, and Full). The If enabled along with the "Validate OWL2 profiles" parameter, the list of valid profiles is taken from the plugin input, without validating the ontology against the profiles in the plugin. The inputs need to include the entity paths "profile" -for the valid profiles, and "ontology" for the ontology IRI. If the "Validate OWL2 profiles" parameter is enabled in the -"Validate" plugin, it can be directly connected to the input of the "Reason" plugin. +for the valid profiles, and "ontology" for the ontology IRI, the latter overriding the setting in the "Reason" plugin. +If the "Validate OWL2 profiles" parameter is enabled in the "Validate" plugin, it can be directly connected to the input +of the "Reason" plugin. ### Maximum RAM Percentage @@ -102,7 +103,8 @@ Maximum heap size for the Java virtual machine in the DI container running the r # Validate -The plugin outputs the explanation as text in Markdown format using the path "markdown". +The plugin outputs the explanation as text in Markdown format on the path "markdown", +the ontology IRI on the path "ontology", and (if enabled) the valid OWL2 profiles in the path "profile". ## Options From 24de7866d39c8d5ee9ed9e8b16a2591ef6d6a117 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Thu, 8 Aug 2024 11:52:39 +0100 Subject: [PATCH 10/32] fixes (CMEM-5913), use custom paramter type for output graph IRI --- CHANGELOG.md | 2 + cmem_plugin_reason/plugin_reason.py | 29 +++++-- cmem_plugin_reason/plugin_validate.py | 36 +++++++-- cmem_plugin_reason/utils.py | 108 +++++++++++++++++++++++--- 4 files changed, 149 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d6755b..51b5a83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p - removed write_md and produce_graph bool parameters - if "input_profiles" is enabled the Reason plugin expects "ontology_iri" and "profile" on the input. The ontology IRI on the input overrides the plugin setting. +- update execution report +- Output graph IRI selectable from existing graphs ## [1.0.0beta4] 2024-07-12 diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index b037fb0..8349faf 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -10,13 +10,14 @@ import validators.url from cmem.cmempy.dp.proxy.graph import get -from cmem_plugin_base.dataintegration.context import ExecutionContext +from cmem_plugin_base.dataintegration.context import ExecutionContext, ExecutionReport from cmem_plugin_base.dataintegration.description import Icon, Plugin, PluginParameter from cmem_plugin_base.dataintegration.entity import Entities, EntityPath, EntitySchema +from cmem_plugin_base.dataintegration.parameter.choice import ChoiceParameterType from cmem_plugin_base.dataintegration.parameter.graph import GraphParameterType from cmem_plugin_base.dataintegration.plugins import WorkflowPlugin from cmem_plugin_base.dataintegration.ports import FixedNumberOfInputs, FixedSchemaPort -from cmem_plugin_base.dataintegration.types import BoolParameterType, StringParameterType +from cmem_plugin_base.dataintegration.types import BoolParameterType from cmem_plugin_base.dataintegration.utils import setup_cmempy_user_access from urllib3.exceptions import InsecureRequestWarning @@ -24,9 +25,9 @@ MAX_RAM_PERCENTAGE_DEFAULT, MAX_RAM_PERCENTAGE_PARAMETER, ONTOLOGY_GRAPH_IRI_PARAMETER, - REASONER_PARAMETER, REASONERS, VALIDATE_PROFILES_PARAMETER, + GraphParameterTypeNew, create_xml_catalog_file, get_graphs_tree, get_provenance, @@ -49,10 +50,16 @@ the reasoning result is written to a specified graph. The following reasoners are supported: ELK, Expression Materializing Reasoner, HermiT, JFact, Structural Reasoner and Whelk.""", parameters=[ - REASONER_PARAMETER, ONTOLOGY_GRAPH_IRI_PARAMETER, VALIDATE_PROFILES_PARAMETER, MAX_RAM_PERCENTAGE_PARAMETER, + PluginParameter( + param_type=ChoiceParameterType(REASONERS), + name="reasoner", + label="Reasoner", + description="Reasoner option. Additionally, enable axiom generators below.", + default_value="", + ), PluginParameter( param_type=GraphParameterType( classes=[ @@ -66,7 +73,7 @@ description="The IRI of the input data graph.", ), PluginParameter( - param_type=StringParameterType(), + param_type=GraphParameterTypeNew(), name="output_graph_iri", label="Result graph IRI", description="The IRI of the output graph for the reasoning result. ⚠️ Existing graphs " @@ -118,7 +125,7 @@ param_type=BoolParameterType(), name="class_assertion", label="ClassAssertion", - description="Generated Axioms", + description="", default_value=False, ), PluginParameter( @@ -266,7 +273,7 @@ def __init__( # noqa: PLR0913, C901 self.input_profiles = input_profiles self.max_ram_percentage = max_ram_percentage - if input_profiles: + if validate_profile and input_profiles: self.input_ports = FixedNumberOfInputs([FixedSchemaPort(self.generate_input_schema())]) else: self.input_ports = FixedNumberOfInputs([]) @@ -358,6 +365,14 @@ def _execute(self, inputs: Sequence[Entities], context: ExecutionContext) -> Non self.post_valid_profiles(inputs, graphs) post_provenance(self, get_provenance(self, context)) + context.report.update( + ExecutionReport( + operation="reason", + operation_desc="ontology and data graph processed.", + entity_count=1, + ) + ) + def execute(self, inputs: Sequence[Entities], context: ExecutionContext) -> None: """Validate input, execute plugin with temporary directory""" if self.input_profiles: diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index 8fadaf9..4ea6ec8 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -10,9 +10,10 @@ import validators.url from cmem.cmempy.dp.proxy.graph import get from cmem.cmempy.workspace.projects.resources.resource import create_resource -from cmem_plugin_base.dataintegration.context import ExecutionContext +from cmem_plugin_base.dataintegration.context import ExecutionContext, ExecutionReport from cmem_plugin_base.dataintegration.description import Icon, Plugin, PluginParameter from cmem_plugin_base.dataintegration.entity import Entities, Entity, EntityPath, EntitySchema +from cmem_plugin_base.dataintegration.parameter.choice import ChoiceParameterType from cmem_plugin_base.dataintegration.plugins import WorkflowPlugin from cmem_plugin_base.dataintegration.ports import FixedNumberOfInputs, FixedSchemaPort from cmem_plugin_base.dataintegration.types import BoolParameterType, StringParameterType @@ -24,9 +25,9 @@ MAX_RAM_PERCENTAGE_DEFAULT, MAX_RAM_PERCENTAGE_PARAMETER, ONTOLOGY_GRAPH_IRI_PARAMETER, - REASONER_PARAMETER, REASONERS, VALIDATE_PROFILES_PARAMETER, + GraphParameterTypeNew, create_xml_catalog_file, get_graphs_tree, get_provenance, @@ -51,12 +52,18 @@ Materializing Reasoner, HermiT, JFact, Structural Reasoner and Whelk.""", icon=Icon(file_name="file-icons--owl.svg", package=__package__), parameters=[ - REASONER_PARAMETER, ONTOLOGY_GRAPH_IRI_PARAMETER, MAX_RAM_PERCENTAGE_PARAMETER, VALIDATE_PROFILES_PARAMETER, PluginParameter( - param_type=StringParameterType(), + param_type=ChoiceParameterType(REASONERS), + name="reasoner", + label="Reasoner", + description="Reasoner option.", + default_value="", + ), + PluginParameter( + param_type=GraphParameterTypeNew(), name="output_graph_iri", label="Output graph IRI", description="The IRI of the output graph for the inconsistency validation. ⚠️ Existing " @@ -228,9 +235,24 @@ def _execute(self, context: ExecutionContext) -> Entities: self.make_resource(context) text = (Path(self.temp) / self.md_filename).read_text() - - if self.stop_at_inconsistencies and text.split("\n", 1)[0] != "No explanations found.": - raise RuntimeError("Inconsistencies found in Ontology.") + if text.split("\n", 1)[0] != "No explanations found.": + if self.stop_at_inconsistencies: + context.report.update( + ExecutionReport( + operation="validate", + error="Inconsistencies found in ontology", + ) + ) + else: + self.log.warning("Inconsistencies found in ontology") + else: + context.report.update( + ExecutionReport( + operation="validate", + operation_desc="ontology validated.", + entity_count=1, + ) + ) return self.make_entities(text, valid_profiles) diff --git a/cmem_plugin_reason/utils.py b/cmem_plugin_reason/utils.py index 1e49cab..46ab768 100644 --- a/cmem_plugin_reason/utils.py +++ b/cmem_plugin_reason/utils.py @@ -6,16 +6,24 @@ from pathlib import Path from secrets import token_hex from subprocess import CompletedProcess, run +from typing import Any from xml.etree.ElementTree import Element, SubElement, tostring -from cmem.cmempy.dp.proxy.graph import get_graph_import_tree, post_streamed +import validators.url +from cmem.cmempy.dp.proxy.graph import get_graph_import_tree, get_graphs_list, post_streamed from cmem.cmempy.dp.proxy.sparql import post as post_select from cmem.cmempy.dp.proxy.update import post as post_update +from cmem_plugin_base.dataintegration.context import ExecutionContext, PluginContext from cmem_plugin_base.dataintegration.description import PluginParameter -from cmem_plugin_base.dataintegration.parameter.choice import ChoiceParameterType from cmem_plugin_base.dataintegration.parameter.graph import GraphParameterType -from cmem_plugin_base.dataintegration.plugins import ExecutionContext, WorkflowPlugin -from cmem_plugin_base.dataintegration.types import BoolParameterType, IntParameterType +from cmem_plugin_base.dataintegration.plugins import WorkflowPlugin +from cmem_plugin_base.dataintegration.types import ( + Autocompletion, + BoolParameterType, + IntParameterType, + StringParameterType, +) +from cmem_plugin_base.dataintegration.utils import setup_cmempy_user_access from defusedxml import minidom from . import __path__ @@ -40,14 +48,6 @@ description="The IRI of the input ontology graph.", ) -REASONER_PARAMETER = PluginParameter( - param_type=ChoiceParameterType(REASONERS), - name="reasoner", - label="Reasoner", - description="Reasoner option.", - default_value="", -) - MAX_RAM_PERCENTAGE_PARAMETER = PluginParameter( param_type=IntParameterType(), name="max_ram_percentage", @@ -230,3 +230,87 @@ def post_profiles(plugin: WorkflowPlugin, valid_profiles: list) -> None: }} """ post_update(query=query) + + +class GraphParameterTypeNew(StringParameterType): + """Knowledge Graph parameter type.""" + + allow_only_autocompleted_values: bool = False + autocomplete_value_with_labels: bool = True + classes: set[str] | None = None + + def __init__( # noqa: PLR0913 + self, + show_di_graphs: bool = False, + show_system_graphs: bool = False, + show_graphs_without_class: bool = False, + classes: list[str] | None = None, + allow_only_autocompleted_values: bool = True, + ): + """Knowledge Graph parameter type. + + :param show_di_graphs: show DI project graphs + :param show_system_graphs: show system graphs such as shape and query catalogs + :param classes: allowed classes of the shown graphs + - if None -> defaults to di:Dataset and void:Dataset + :param allow_only_autocompleted_values: allow entering new graph URLs + """ + self.show_di_graphs = show_di_graphs + self.show_system_graphs = show_system_graphs + self.show_graphs_without_class = show_graphs_without_class + self.allow_only_autocompleted_values = allow_only_autocompleted_values + if classes: + self.classes = set(classes) + else: + self.classes = { + "https://vocab.eccenca.com/di/Dataset", + "http://rdfs.org/ns/void#Dataset", + } + + def autocomplete( # noqa: C901 + self, + query_terms: list[str], + depend_on_parameter_values: list[Any], # noqa: ARG002 + context: PluginContext, + ) -> list[Autocompletion]: + """Autocomplete""" + setup_cmempy_user_access(context=context.user) + graphs = get_graphs_list() + result = [] + for _ in graphs: + iri = _["iri"] + title = _["label"]["title"] + label = f"{title} ({iri})" + assigned_classes = set(_["assignedClasses"]) + # ignore DI project graphs + if self.show_di_graphs is False and _["diProjectGraph"]: + continue + # ignore system resource graphs + if self.show_system_graphs is False and _["systemResource"]: + continue + # show graphs without assigned classes only if explicitly wanted + if not assigned_classes: + if self.show_graphs_without_class: + result.append(Autocompletion(value=iri, label=label)) + continue + # ignore graphs which do not match the requested classes + if ( + self.classes + and assigned_classes + and not self.classes.intersection(assigned_classes) + ): + continue + str_match = True + for term in query_terms: + if term.lower() not in label.lower(): + str_match = False + break + if str_match: + result.append(Autocompletion(value=iri, label=label)) + if not result and len(query_terms) == 1 and validators.url(query_terms[0]): + result.append( + Autocompletion(value=query_terms[0], label=f"new graph: {query_terms[0]}") + ) + + result.sort(key=lambda x: x.label) + return list(set(result)) From a8b5ca5cbe4fb38bf01d48b568eed93f1091e171 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Thu, 8 Aug 2024 12:00:32 +0100 Subject: [PATCH 11/32] edit parameter description --- cmem_plugin_reason/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmem_plugin_reason/utils.py b/cmem_plugin_reason/utils.py index 46ab768..95bb321 100644 --- a/cmem_plugin_reason/utils.py +++ b/cmem_plugin_reason/utils.py @@ -52,8 +52,8 @@ param_type=IntParameterType(), name="max_ram_percentage", label="Maximum RAM Percentage", - description="""Maximum heap size for the Java virtual machine in the DI container running the - reasoning process. ⚠️ Setting the percentage too high may result in an out of memory error.""", + description="""Maximum heap size for the reasoning process in the DI container. ⚠️ Setting the + percentage too high may result in an out of memory error.""", default_value=MAX_RAM_PERCENTAGE_DEFAULT, advanced=True, ) From 8e6120d6f14df2f82c534e5fa0f35f4d1362365b Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Thu, 8 Aug 2024 13:35:21 +0100 Subject: [PATCH 12/32] init ExecutionReport --- cmem_plugin_reason/plugin_reason.py | 6 +++++ cmem_plugin_reason/plugin_validate.py | 32 +++++++++++++++++---------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index 8349faf..0fadf2d 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -375,6 +375,12 @@ def _execute(self, inputs: Sequence[Entities], context: ExecutionContext) -> Non def execute(self, inputs: Sequence[Entities], context: ExecutionContext) -> None: """Validate input, execute plugin with temporary directory""" + context.report.update( + ExecutionReport( + operation="reason", + operation_desc="ontologies and data graphs processed.", + ) + ) if self.input_profiles: errors = "" values = next(inputs[0].entities).values diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index 4ea6ec8..79bdf16 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -131,6 +131,16 @@ def __init__( # noqa: PLR0913 self.schema = self.generate_output_schema() self.output_port = FixedSchemaPort(self.schema) + def generate_output_schema(self) -> EntitySchema: + """Generate the output schema.""" + paths = [EntityPath(path="markdown"), EntityPath(path="ontology")] + if self.validate_profile: + paths.append(EntityPath(path="profile")) + return EntitySchema( + type_uri="https://eccenca.com/plugin_validateontology/type", + paths=paths, + ) + def get_graphs(self, graphs: dict, context: ExecutionContext) -> None: """Get graphs from CMEM""" for graph in graphs: @@ -189,16 +199,6 @@ def add_profiles(self, valid_profiles: list) -> list: post_profiles(self, valid_profiles) return valid_profiles - def generate_output_schema(self) -> EntitySchema: - """Generate the output schema.""" - paths = [EntityPath(path="markdown"), EntityPath(path="ontology")] - if self.validate_profile: - paths.append(EntityPath(path="profile")) - return EntitySchema( - type_uri="https://eccenca.com/plugin_validateontology/type", - paths=paths, - ) - def make_entities(self, text: str, valid_profiles: list) -> Entities: """Make entities""" values = [[text], [self.ontology_graph_iri]] @@ -240,11 +240,13 @@ def _execute(self, context: ExecutionContext) -> Entities: context.report.update( ExecutionReport( operation="validate", - error="Inconsistencies found in ontology", + error="Inconsistencies found in ontology.", + operation_desc="ontologies processed.", + entity_count=1, ) ) else: - self.log.warning("Inconsistencies found in ontology") + self.log.warning("Inconsistencies found in ontology.") else: context.report.update( ExecutionReport( @@ -258,5 +260,11 @@ def _execute(self, context: ExecutionContext) -> Entities: def execute(self, inputs: tuple, context: ExecutionContext) -> Entities: # noqa: ARG002 """Remove temp files on error""" + context.report.update( + ExecutionReport( + operation="validate", + operation_desc="ontologies validated.", + ) + ) with TemporaryDirectory() as self.temp: return self._execute(context) From 73ee56be3184bc6ecaab5f6efc0a6f315006ac8f Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Thu, 8 Aug 2024 15:41:15 +0100 Subject: [PATCH 13/32] edit parameter label --- cmem_plugin_reason/plugin_reason.py | 4 ++-- cmem_plugin_reason/plugin_validate.py | 2 +- cmem_plugin_reason/utils.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index 0fadf2d..f13678b 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -57,7 +57,7 @@ param_type=ChoiceParameterType(REASONERS), name="reasoner", label="Reasoner", - description="Reasoner option. Additionally, enable axiom generators below.", + description="Reasoner option. Additionally, select axiom generators below.", default_value="", ), PluginParameter( @@ -282,7 +282,7 @@ def __init__( # noqa: PLR0913, C901 def generate_input_schema(self) -> EntitySchema: """Generate the output schema.""" return EntitySchema( - type_uri="urn:row", + type_uri="reason", paths=[EntityPath(path="profile"), EntityPath(path="ontology")], ) diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index 79bdf16..0558929 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -137,7 +137,7 @@ def generate_output_schema(self) -> EntitySchema: if self.validate_profile: paths.append(EntityPath(path="profile")) return EntitySchema( - type_uri="https://eccenca.com/plugin_validateontology/type", + type_uri="validate", paths=paths, ) diff --git a/cmem_plugin_reason/utils.py b/cmem_plugin_reason/utils.py index 95bb321..b157a16 100644 --- a/cmem_plugin_reason/utils.py +++ b/cmem_plugin_reason/utils.py @@ -44,7 +44,7 @@ ONTOLOGY_GRAPH_IRI_PARAMETER = PluginParameter( param_type=GraphParameterType(classes=["http://www.w3.org/2002/07/owl#Ontology"]), name="ontology_graph_iri", - label="Ontology_graph_IRI", + label="Ontology graph IRI", description="The IRI of the input ontology graph.", ) From dd5a6543e9d3b7bd144a893f4c971ed0fd8c82c9 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Thu, 8 Aug 2024 16:00:57 +0100 Subject: [PATCH 14/32] use GraphParameterType(allow_only_autocompleted_values=False) instead of custom parameter for output graph IRI --- cmem_plugin_reason/plugin_reason.py | 10 +-- cmem_plugin_reason/plugin_validate.py | 10 +-- cmem_plugin_reason/utils.py | 106 +++----------------------- 3 files changed, 15 insertions(+), 111 deletions(-) diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index f13678b..93dc84f 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -25,9 +25,9 @@ MAX_RAM_PERCENTAGE_DEFAULT, MAX_RAM_PERCENTAGE_PARAMETER, ONTOLOGY_GRAPH_IRI_PARAMETER, + OUTPUT_GRAPH_IRI_PARAMETER, REASONERS, VALIDATE_PROFILES_PARAMETER, - GraphParameterTypeNew, create_xml_catalog_file, get_graphs_tree, get_provenance, @@ -51,6 +51,7 @@ ELK, Expression Materializing Reasoner, HermiT, JFact, Structural Reasoner and Whelk.""", parameters=[ ONTOLOGY_GRAPH_IRI_PARAMETER, + OUTPUT_GRAPH_IRI_PARAMETER, VALIDATE_PROFILES_PARAMETER, MAX_RAM_PERCENTAGE_PARAMETER, PluginParameter( @@ -72,13 +73,6 @@ label="Data graph IRI", description="The IRI of the input data graph.", ), - PluginParameter( - param_type=GraphParameterTypeNew(), - name="output_graph_iri", - label="Result graph IRI", - description="The IRI of the output graph for the reasoning result. ⚠️ Existing graphs " - "will be overwritten.", - ), PluginParameter( param_type=BoolParameterType(), name="sub_class", diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index 0558929..5ef3774 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -25,9 +25,9 @@ MAX_RAM_PERCENTAGE_DEFAULT, MAX_RAM_PERCENTAGE_PARAMETER, ONTOLOGY_GRAPH_IRI_PARAMETER, + OUTPUT_GRAPH_IRI_PARAMETER, REASONERS, VALIDATE_PROFILES_PARAMETER, - GraphParameterTypeNew, create_xml_catalog_file, get_graphs_tree, get_provenance, @@ -55,6 +55,7 @@ ONTOLOGY_GRAPH_IRI_PARAMETER, MAX_RAM_PERCENTAGE_PARAMETER, VALIDATE_PROFILES_PARAMETER, + OUTPUT_GRAPH_IRI_PARAMETER, PluginParameter( param_type=ChoiceParameterType(REASONERS), name="reasoner", @@ -62,13 +63,6 @@ description="Reasoner option.", default_value="", ), - PluginParameter( - param_type=GraphParameterTypeNew(), - name="output_graph_iri", - label="Output graph IRI", - description="The IRI of the output graph for the inconsistency validation. ⚠️ Existing " - "graphs will be overwritten.", - ), PluginParameter( param_type=StringParameterType(), name="md_filename", diff --git a/cmem_plugin_reason/utils.py b/cmem_plugin_reason/utils.py index b157a16..e0daf8e 100644 --- a/cmem_plugin_reason/utils.py +++ b/cmem_plugin_reason/utils.py @@ -6,24 +6,16 @@ from pathlib import Path from secrets import token_hex from subprocess import CompletedProcess, run -from typing import Any from xml.etree.ElementTree import Element, SubElement, tostring -import validators.url -from cmem.cmempy.dp.proxy.graph import get_graph_import_tree, get_graphs_list, post_streamed +from cmem.cmempy.dp.proxy.graph import get_graph_import_tree, post_streamed from cmem.cmempy.dp.proxy.sparql import post as post_select from cmem.cmempy.dp.proxy.update import post as post_update -from cmem_plugin_base.dataintegration.context import ExecutionContext, PluginContext +from cmem_plugin_base.dataintegration.context import ExecutionContext from cmem_plugin_base.dataintegration.description import PluginParameter from cmem_plugin_base.dataintegration.parameter.graph import GraphParameterType from cmem_plugin_base.dataintegration.plugins import WorkflowPlugin -from cmem_plugin_base.dataintegration.types import ( - Autocompletion, - BoolParameterType, - IntParameterType, - StringParameterType, -) -from cmem_plugin_base.dataintegration.utils import setup_cmempy_user_access +from cmem_plugin_base.dataintegration.types import BoolParameterType, IntParameterType from defusedxml import minidom from . import __path__ @@ -67,6 +59,14 @@ default_value=False, ) +OUTPUT_GRAPH_IRI_PARAMETER = PluginParameter( + param_type=GraphParameterType(allow_only_autocompleted_values=False), + name="output_graph_iri", + label="Output graph IRI", + description="""The IRI of the output graph for the inconsistency validation. ⚠️ Existing graphs + graphs will be overwritten.""", +) + def create_xml_catalog_file(dir_: str, graphs: dict) -> None: """Create XML catalog file""" @@ -230,87 +230,3 @@ def post_profiles(plugin: WorkflowPlugin, valid_profiles: list) -> None: }} """ post_update(query=query) - - -class GraphParameterTypeNew(StringParameterType): - """Knowledge Graph parameter type.""" - - allow_only_autocompleted_values: bool = False - autocomplete_value_with_labels: bool = True - classes: set[str] | None = None - - def __init__( # noqa: PLR0913 - self, - show_di_graphs: bool = False, - show_system_graphs: bool = False, - show_graphs_without_class: bool = False, - classes: list[str] | None = None, - allow_only_autocompleted_values: bool = True, - ): - """Knowledge Graph parameter type. - - :param show_di_graphs: show DI project graphs - :param show_system_graphs: show system graphs such as shape and query catalogs - :param classes: allowed classes of the shown graphs - - if None -> defaults to di:Dataset and void:Dataset - :param allow_only_autocompleted_values: allow entering new graph URLs - """ - self.show_di_graphs = show_di_graphs - self.show_system_graphs = show_system_graphs - self.show_graphs_without_class = show_graphs_without_class - self.allow_only_autocompleted_values = allow_only_autocompleted_values - if classes: - self.classes = set(classes) - else: - self.classes = { - "https://vocab.eccenca.com/di/Dataset", - "http://rdfs.org/ns/void#Dataset", - } - - def autocomplete( # noqa: C901 - self, - query_terms: list[str], - depend_on_parameter_values: list[Any], # noqa: ARG002 - context: PluginContext, - ) -> list[Autocompletion]: - """Autocomplete""" - setup_cmempy_user_access(context=context.user) - graphs = get_graphs_list() - result = [] - for _ in graphs: - iri = _["iri"] - title = _["label"]["title"] - label = f"{title} ({iri})" - assigned_classes = set(_["assignedClasses"]) - # ignore DI project graphs - if self.show_di_graphs is False and _["diProjectGraph"]: - continue - # ignore system resource graphs - if self.show_system_graphs is False and _["systemResource"]: - continue - # show graphs without assigned classes only if explicitly wanted - if not assigned_classes: - if self.show_graphs_without_class: - result.append(Autocompletion(value=iri, label=label)) - continue - # ignore graphs which do not match the requested classes - if ( - self.classes - and assigned_classes - and not self.classes.intersection(assigned_classes) - ): - continue - str_match = True - for term in query_terms: - if term.lower() not in label.lower(): - str_match = False - break - if str_match: - result.append(Autocompletion(value=iri, label=label)) - if not result and len(query_terms) == 1 and validators.url(query_terms[0]): - result.append( - Autocompletion(value=query_terms[0], label=f"new graph: {query_terms[0]}") - ) - - result.sort(key=lambda x: x.label) - return list(set(result)) From 0b1aac0b29e921d49c3ea8917eafc6608abfc539 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Thu, 8 Aug 2024 16:12:09 +0100 Subject: [PATCH 15/32] set allowed classes for output graph list to Dataset and Ontology --- cmem_plugin_reason/utils.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cmem_plugin_reason/utils.py b/cmem_plugin_reason/utils.py index e0daf8e..1f897b6 100644 --- a/cmem_plugin_reason/utils.py +++ b/cmem_plugin_reason/utils.py @@ -60,7 +60,14 @@ ) OUTPUT_GRAPH_IRI_PARAMETER = PluginParameter( - param_type=GraphParameterType(allow_only_autocompleted_values=False), + param_type=GraphParameterType( + allow_only_autocompleted_values=False, + classes=[ + "https://vocab.eccenca.com/di/Dataset", + "http://rdfs.org/ns/void#Dataset", + "http://www.w3.org/2002/07/owl#Ontology", + ], + ), name="output_graph_iri", label="Output graph IRI", description="""The IRI of the output graph for the inconsistency validation. ⚠️ Existing graphs From 49ff6bacf82e7897035468d96d2041e3a21f2713 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Thu, 8 Aug 2024 16:14:53 +0100 Subject: [PATCH 16/32] fix indentation --- cmem_plugin_reason/utils.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cmem_plugin_reason/utils.py b/cmem_plugin_reason/utils.py index 1f897b6..c4cb699 100644 --- a/cmem_plugin_reason/utils.py +++ b/cmem_plugin_reason/utils.py @@ -149,14 +149,14 @@ def get_provenance(plugin: WorkflowPlugin, context: ExecutionContext) -> dict | project_graph = f"http://di.eccenca.com/project/{context.task.project_id()}" type_query = f""" - SELECT ?type ?label {{ - GRAPH <{project_graph}> {{ - <{plugin_iri}> a ?type . - <{plugin_iri}> ?label . - FILTER(STRSTARTS(STR(?type), "https://vocab.eccenca.com/di/functions/")) - }} + SELECT ?type ?label {{ + GRAPH <{project_graph}> {{ + <{plugin_iri}> a ?type . + <{plugin_iri}> ?label . + FILTER(STRSTARTS(STR(?type), "https://vocab.eccenca.com/di/functions/")) }} - """ + }} + """ result = json.loads(post_select(query=type_query)) From 3441702e773c126d783f81083576eeddf4e951d9 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Fri, 9 Aug 2024 13:42:29 +0100 Subject: [PATCH 17/32] removee reason merge in reason --- cmem_plugin_reason/plugin_reason.py | 23 +++++++++--------- cmem_plugin_reason/plugin_validate.py | 17 ++++++------- cmem_plugin_reason/utils.py | 35 +++++++++++++-------------- 3 files changed, 35 insertions(+), 40 deletions(-) diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index 93dc84f..4360179 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -276,25 +276,25 @@ def __init__( # noqa: PLR0913, C901 def generate_input_schema(self) -> EntitySchema: """Generate the output schema.""" return EntitySchema( - type_uri="reason", - paths=[EntityPath(path="profile"), EntityPath(path="ontology")], + type_uri="validate", + paths=[EntityPath("profile"), EntityPath("ontology")], ) def get_graphs(self, graphs: dict, context: ExecutionContext) -> None: """Get graphs from CMEM""" - for graph in graphs: - self.log.info(f"Fetching graph {graph}.") - with (Path(self.temp) / graphs[graph]).open("w", encoding="utf-8") as file: + for iri, filename in graphs.items(): + self.log.info(f"Fetching graph {iri}.") + with (Path(self.temp) / filename).open("w", encoding="utf-8") as file: setup_cmempy_user_access(context.user) - for line in get(graph).text.splitlines(): + for line in get(iri).text.splitlines(): if line != ( - f"<{graph}> " + f"<{iri}> " f"<{self.output_graph_iri}> ." ): file.write(line + "\n") - if graph == self.data_graph_iri: + if iri == self.data_graph_iri: file.write( - f"<{graph}> " + f"<{iri}> " f"<{self.ontology_graph_iri}> ." ) @@ -304,9 +304,8 @@ def reason(self, graphs: dict) -> None: data_location = f"{self.temp}/{graphs[self.data_graph_iri]}" utctime = str(datetime.fromtimestamp(int(time()), tz=UTC))[:-6].replace(" ", "T") + "Z" cmd = ( - f'merge --input "{data_location}" ' - "--collapse-import-closure false " - f"reason --reasoner {self.reasoner} " + f'reason --input "{data_location}" ' + f"--reasoner {self.reasoner} " f'--axiom-generators "{axioms}" ' f"--include-indirect true " f"--exclude-duplicate-axioms true " diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index 5ef3774..fcd21dc 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -127,21 +127,18 @@ def __init__( # noqa: PLR0913 def generate_output_schema(self) -> EntitySchema: """Generate the output schema.""" - paths = [EntityPath(path="markdown"), EntityPath(path="ontology")] + paths = [EntityPath("markdown"), EntityPath("ontology")] if self.validate_profile: - paths.append(EntityPath(path="profile")) - return EntitySchema( - type_uri="validate", - paths=paths, - ) + paths.append(EntityPath("profile")) + return EntitySchema(type_uri="validate", paths=paths) def get_graphs(self, graphs: dict, context: ExecutionContext) -> None: """Get graphs from CMEM""" - for graph in graphs: - self.log.info(f"Fetching graph {graph}.") - with (Path(self.temp) / graphs[graph]).open("w", encoding="utf-8") as file: + for iri, filename in graphs.items(): + self.log.info(f"Fetching graph {iri}.") + with (Path(self.temp) / filename).open("w", encoding="utf-8") as file: setup_cmempy_user_access(context.user) - file.write(get(graph).text) + file.write(get(iri).text) def explain(self, graphs: dict) -> None: """Reason""" diff --git a/cmem_plugin_reason/utils.py b/cmem_plugin_reason/utils.py index c4cb699..c1df298 100644 --- a/cmem_plugin_reason/utils.py +++ b/cmem_plugin_reason/utils.py @@ -120,25 +120,24 @@ def send_result(iri: str, filepath: Path) -> None: def post_provenance(plugin: WorkflowPlugin, prov: dict | None) -> None: """Post provenance""" - if not prov: - return - param_sparql = "" - for name, iri in prov["parameters"].items(): - param_sparql += f'\n<{prov["plugin_iri"]}> <{iri}> "{plugin.__dict__[name]}" .' - insert_query = f""" - INSERT DATA {{ - GRAPH <{plugin.output_graph_iri}> {{ - <{plugin.output_graph_iri}> - <{prov["plugin_iri"]}> . - <{prov["plugin_iri"]}> a <{prov["plugin_type"]}>, - . - <{prov["plugin_iri"]}> - "{prov['plugin_label']}" . - {param_sparql} + if prov: + param_sparql = "" + for name, iri in prov["parameters"].items(): + param_sparql += f'\n<{prov["plugin_iri"]}> <{iri}> "{plugin.__dict__[name]}" .' + insert_query = f""" + INSERT DATA {{ + GRAPH <{plugin.output_graph_iri}> {{ + <{plugin.output_graph_iri}> + <{prov["plugin_iri"]}> . + <{prov["plugin_iri"]}> a <{prov["plugin_type"]}>, + . + <{prov["plugin_iri"]}> + "{prov['plugin_label']}" . + {param_sparql} + }} }} - }} - """ - post_update(query=insert_query) + """ + post_update(query=insert_query) def get_provenance(plugin: WorkflowPlugin, context: ExecutionContext) -> dict | None: From 021f78f5de652007c07aabca3a5597b4bfd7362c Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Fri, 9 Aug 2024 14:02:12 +0100 Subject: [PATCH 18/32] remove robot merge in Validate --- cmem_plugin_reason/plugin_validate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index fcd21dc..e5ae683 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -146,8 +146,8 @@ def explain(self, graphs: dict) -> None: utctime = str(datetime.fromtimestamp(int(time()), tz=UTC))[:-6].replace(" ", "T") + "Z" cmd = ( - f'merge --input "{data_location}" ' - f"explain --reasoner {self.reasoner} -M inconsistency " + f'explain --input "{data_location}" ' + f"--reasoner {self.reasoner} -M inconsistency " f'--explanation "{self.temp}/{self.md_filename}"' ) From bc6cf5ea054c2eee08ef3e0d2538029b4350e8f3 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Mon, 12 Aug 2024 12:15:11 +0100 Subject: [PATCH 19/32] refactor parameter variable generation --- cmem_plugin_reason/plugin_reason.py | 19 +++++-------------- cmem_plugin_reason/plugin_validate.py | 3 --- poetry.lock | 19 +++++++++++++++---- pyproject.toml | 1 + 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index 4360179..176836b 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -19,6 +19,7 @@ from cmem_plugin_base.dataintegration.ports import FixedNumberOfInputs, FixedSchemaPort from cmem_plugin_base.dataintegration.types import BoolParameterType from cmem_plugin_base.dataintegration.utils import setup_cmempy_user_access +from inflection import underscore from urllib3.exceptions import InsecureRequestWarning from cmem_plugin_reason.utils import ( @@ -245,20 +246,7 @@ def __init__( # noqa: PLR0913, C901 errors += 'Invalid value for parameter "Maximum RAM Percentage". ' if errors: raise ValueError(errors[:-1]) - self.sub_class = sub_class - self.equivalent_class = equivalent_class - self.disjoint_classes = disjoint_classes - self.data_property_characteristic = data_property_characteristic - self.equivalent_data_properties = equivalent_data_properties - self.sub_data_property = sub_data_property - self.class_assertion = class_assertion - self.property_assertion = property_assertion - self.equivalent_object_property = equivalent_object_property - self.inverse_object_properties = inverse_object_properties - self.object_property_characteristic = object_property_characteristic - self.sub_object_property = sub_object_property - self.object_property_range = object_property_range - self.object_property_domain = object_property_domain + self.data_graph_iri = data_graph_iri self.ontology_graph_iri = ontology_graph_iri self.output_graph_iri = output_graph_iri @@ -267,6 +255,9 @@ def __init__( # noqa: PLR0913, C901 self.input_profiles = input_profiles self.max_ram_percentage = max_ram_percentage + for k, v in self.axioms.items(): + self.__dict__[underscore(k)] = v + if validate_profile and input_profiles: self.input_ports = FixedNumberOfInputs([FixedSchemaPort(self.generate_input_schema())]) else: diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index e5ae683..475ff32 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -144,13 +144,11 @@ def explain(self, graphs: dict) -> None: """Reason""" data_location = f"{self.temp}/{graphs[self.ontology_graph_iri]}" utctime = str(datetime.fromtimestamp(int(time()), tz=UTC))[:-6].replace(" ", "T") + "Z" - cmd = ( f'explain --input "{data_location}" ' f"--reasoner {self.reasoner} -M inconsistency " f'--explanation "{self.temp}/{self.md_filename}"' ) - if self.output_graph_iri: cmd += ( f' annotate --ontology-iri "{self.output_graph_iri}" ' @@ -161,7 +159,6 @@ def explain(self, graphs: dict) -> None: f'--typed-annotation dc:created "{utctime}" xsd:dateTime ' f'--output "{self.temp}/output.ttl"' ) - response = robot(cmd, self.max_ram_percentage) if response.returncode != 0: if response.stdout: diff --git a/poetry.lock b/poetry.lock index 627c38f..2d5c841 100644 --- a/poetry.lock +++ b/poetry.lock @@ -316,6 +316,17 @@ files = [ {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, ] +[[package]] +name = "inflection" +version = "0.5.1" +description = "A port of Ruby on Rails inflector to Python" +optional = false +python-versions = ">=3.5" +files = [ + {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, + {file = "inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417"}, +] + [[package]] name = "iniconfig" version = "2.0.0" @@ -1080,13 +1091,13 @@ files = [ [[package]] name = "textual" -version = "0.75.1" +version = "0.76.0" description = "Modern Text User Interface framework" optional = false python-versions = "<4.0.0,>=3.8.1" files = [ - {file = "textual-0.75.1-py3-none-any.whl", hash = "sha256:7edb1196753feae79890daa2287bc3180ebba2cbf63f59f2a160991325b020f2"}, - {file = "textual-0.75.1.tar.gz", hash = "sha256:3f0b53fe6119aa64853c7e60ced4d4e16fb23c83dee1e0fd19eddb3f2639c02e"}, + {file = "textual-0.76.0-py3-none-any.whl", hash = "sha256:e2035609c889dba507d34a5d7b333f1c8c53a29fb170962cb92101507663517a"}, + {file = "textual-0.76.0.tar.gz", hash = "sha256:b12e8879d591090c0901b5cb8121d086e28e677353b368292d3865ec99b83b70"}, ] [package.dependencies] @@ -1156,4 +1167,4 @@ crypto-eth-addresses = ["eth-hash[pycryptodome] (>=0.7.0)"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "91185650bb2b1c410b5d4927d0bac77b10393064c5052e199219c82385fbfda5" +content-hash = "4df369a43e71446c9cbc562df56387e5f6607d84851c42188d3799874a8848bf" diff --git a/pyproject.toml b/pyproject.toml index 27eac91..9e6ef0c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ validators = "^0.33.0" pathvalidate = "^3.2.0" defusedxml = "^0.7.1" urllib3 = "^2.2.2" +inflection = "^0.5.1" [tool.poetry.dependencies.cmem-plugin-base] version = "^4.5.0" From 7ff5ff943fb3d66efadc134fd192aa96352e9b22 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Mon, 12 Aug 2024 14:07:29 +0100 Subject: [PATCH 20/32] add '[processed ontology] a owl:Ontology' to output graph, use config port input for valid OWL2 profiles in Reasin plugin --- CHANGELOG.md | 2 + README.md | 6 +-- cmem_plugin_reason/plugin_reason.py | 71 ++++++++++----------------- cmem_plugin_reason/plugin_validate.py | 8 +-- cmem_plugin_reason/utils.py | 2 +- tests/test_elk.ttl | 3 +- tests/test_emr.ttl | 3 +- tests/test_hermit.ttl | 3 +- tests/test_jfact.ttl | 3 +- tests/test_reason.py | 9 ++-- tests/test_structural.ttl | 3 +- tests/test_validate_output.ttl | 3 +- tests/test_whelk.ttl | 3 +- 13 files changed, 53 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51b5a83..6a39aa0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p The ontology IRI on the input overrides the plugin setting. - update execution report - Output graph IRI selectable from existing graphs +- When "input_profiles" is enabled the ontology IRI and list of valid OWL2 profiles is now taken from the config port. +The list of valid profiles is a comma-separated string (e.g. "Full,DL") ## [1.0.0beta4] 2024-07-12 diff --git a/README.md b/README.md index a445a73..9bde745 100644 --- a/README.md +++ b/README.md @@ -88,10 +88,8 @@ Validate the input ontology against OWL profiles (DL, EL, QL, RL, and Full). The ### Process valid OWL profiles from input -If enabled along with the "Validate OWL2 profiles" parameter, the list of valid profiles is taken from the plugin input, -without validating the ontology against the profiles in the plugin. The inputs need to include the entity paths "profile" -for the valid profiles, and "ontology" for the ontology IRI, the latter overriding the setting in the "Reason" plugin. -If the "Validate OWL2 profiles" parameter is enabled in the "Validate" plugin, it can be directly connected to the input +If enabled along with the "Validate OWL2 profiles" parameter, the ontology IRI and list of valid profiles is taken from the config port input, +without validating the ontology against the profiles in the plugin. If the "Validate OWL2 profiles" parameter is enabled in the "Validate" plugin, it can be directly connected to the input of the "Reason" plugin. diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index 176836b..e56eebc 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -1,6 +1,5 @@ """Reasoning workflow plugin module""" -from collections.abc import Sequence from datetime import UTC, datetime from os import environ from pathlib import Path @@ -12,12 +11,12 @@ from cmem.cmempy.dp.proxy.graph import get from cmem_plugin_base.dataintegration.context import ExecutionContext, ExecutionReport from cmem_plugin_base.dataintegration.description import Icon, Plugin, PluginParameter -from cmem_plugin_base.dataintegration.entity import Entities, EntityPath, EntitySchema +from cmem_plugin_base.dataintegration.entity import EntityPath, EntitySchema from cmem_plugin_base.dataintegration.parameter.choice import ChoiceParameterType from cmem_plugin_base.dataintegration.parameter.graph import GraphParameterType from cmem_plugin_base.dataintegration.plugins import WorkflowPlugin -from cmem_plugin_base.dataintegration.ports import FixedNumberOfInputs, FixedSchemaPort -from cmem_plugin_base.dataintegration.types import BoolParameterType +from cmem_plugin_base.dataintegration.ports import FixedNumberOfInputs +from cmem_plugin_base.dataintegration.types import BoolParameterType, StringParameterType from cmem_plugin_base.dataintegration.utils import setup_cmempy_user_access from inflection import underscore from urllib3.exceptions import InsecureRequestWarning @@ -177,11 +176,20 @@ name="input_profiles", label="Process valid OWL profiles from input", description="""If the "validate OWL profiles" parameter is enabled, the valid profiles - and ontology IRI is taken from the input (paths "profile" and "ontology") instead of - running the validation in the plugin.""", + and ontology IRI is taken from the config port input (parameters "valid_profiles" and + "ontology_graph_iri") instead of from running the validation in the plugin. The valid + profiles input is a comma-separated string (e.g. "Full,DL").""", default_value=False, advanced=True, ), + PluginParameter( + param_type=StringParameterType(), + name="valid_profiles", + label="Valid OWL2 profiles", + description="Valid OWL2 profiles for the processed ontology.", + default_value="", + visible=False, + ), ], ) class ReasonPlugin(WorkflowPlugin): @@ -210,6 +218,7 @@ def __init__( # noqa: PLR0913, C901 validate_profile: bool = False, input_profiles: bool = False, max_ram_percentage: int = MAX_RAM_PERCENTAGE_DEFAULT, + valid_profiles: str = "", ) -> None: self.axioms = { "SubClass": sub_class, @@ -254,14 +263,12 @@ def __init__( # noqa: PLR0913, C901 self.validate_profile = validate_profile self.input_profiles = input_profiles self.max_ram_percentage = max_ram_percentage + self.valid_profiles = valid_profiles for k, v in self.axioms.items(): self.__dict__[underscore(k)] = v - if validate_profile and input_profiles: - self.input_ports = FixedNumberOfInputs([FixedSchemaPort(self.generate_input_schema())]) - else: - self.input_ports = FixedNumberOfInputs([]) + self.input_ports = FixedNumberOfInputs([]) self.output_port = None def generate_input_schema(self) -> EntitySchema: @@ -324,17 +331,7 @@ def reason(self, graphs: dict) -> None: raise OSError(response.stderr.decode()) raise OSError("ROBOT error") - def post_valid_profiles(self, inputs: Sequence[Entities], graphs: dict) -> None: - """Post valid profiles. Optionally get valid profiles from input.""" - if self.input_profiles: - values = next(inputs[0].entities).values - paths = [p.path for p in inputs[0].schema.paths] - valid_profiles = values[paths.index("profile")] - else: - valid_profiles = validate_profiles(self, graphs) - post_profiles(self, valid_profiles) - - def _execute(self, inputs: Sequence[Entities], context: ExecutionContext) -> None: + def _execute(self, context: ExecutionContext) -> None: """`Execute plugin""" setup_cmempy_user_access(context.user) graphs = get_graphs_tree( @@ -346,7 +343,11 @@ def _execute(self, inputs: Sequence[Entities], context: ExecutionContext) -> Non setup_cmempy_user_access(context.user) send_result(self.output_graph_iri, Path(self.temp) / "result.ttl") if self.validate_profile: - self.post_valid_profiles(inputs, graphs) + if self.input_profiles: + valid_profiles = self.valid_profiles.split(",") + else: + valid_profiles = validate_profiles(self, graphs) + post_profiles(self, valid_profiles) post_provenance(self, get_provenance(self, context)) context.report.update( @@ -357,7 +358,7 @@ def _execute(self, inputs: Sequence[Entities], context: ExecutionContext) -> Non ) ) - def execute(self, inputs: Sequence[Entities], context: ExecutionContext) -> None: + def execute(self, inputs: None, context: ExecutionContext) -> None: # noqa: ARG002 """Validate input, execute plugin with temporary directory""" context.report.update( ExecutionReport( @@ -365,27 +366,5 @@ def execute(self, inputs: Sequence[Entities], context: ExecutionContext) -> None operation_desc="ontologies and data graphs processed.", ) ) - if self.input_profiles: - errors = "" - values = next(inputs[0].entities).values - paths = [p.path for p in inputs[0].schema.paths] - if not inputs: - raise OSError( - 'Input entities needed if "Process valid OWL profiles from input" is enabled' - ) - if "profile" not in paths: - errors += 'No value for "profile" given on input. ' - if "ontology" not in paths: - errors += 'No value for "ontology" given on input. ' - self.ontology_graph_iri = values[paths.index("ontology")][0] - if not validators.url(self.ontology_graph_iri): - errors += 'Invalid IRI for parameter "Ontology graph IRI". ' - if self.ontology_graph_iri == self.data_graph_iri: - errors += "Ontology graph IRI cannot be the same as the data graph IRI. " - if self.ontology_graph_iri == self.output_graph_iri: - errors += "Ontology graph IRI cannot be the same as the output graph IRI. " - if errors: - raise ValueError(errors[:-1]) - with TemporaryDirectory() as self.temp: - self._execute(inputs, context) + self._execute(context) diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index 475ff32..be185a9 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -127,9 +127,9 @@ def __init__( # noqa: PLR0913 def generate_output_schema(self) -> EntitySchema: """Generate the output schema.""" - paths = [EntityPath("markdown"), EntityPath("ontology")] + paths = [EntityPath("markdown"), EntityPath("ontology_graph_iri")] if self.validate_profile: - paths.append(EntityPath("profile")) + paths.append(EntityPath("valid_profiles")) return EntitySchema(type_uri="validate", paths=paths) def get_graphs(self, graphs: dict, context: ExecutionContext) -> None: @@ -191,7 +191,7 @@ def make_entities(self, text: str, valid_profiles: list) -> Entities: """Make entities""" values = [[text], [self.ontology_graph_iri]] if self.validate_profile: - values.append(valid_profiles) + values.append([",".join(valid_profiles)]) entities = [ Entity( uri="https://eccenca.com/plugin_validateontology/result", @@ -246,7 +246,7 @@ def _execute(self, context: ExecutionContext) -> Entities: return self.make_entities(text, valid_profiles) - def execute(self, inputs: tuple, context: ExecutionContext) -> Entities: # noqa: ARG002 + def execute(self, inputs: None, context: ExecutionContext) -> Entities: # noqa: ARG002 """Remove temp files on error""" context.report.update( ExecutionReport( diff --git a/cmem_plugin_reason/utils.py b/cmem_plugin_reason/utils.py index c1df298..ab276a8 100644 --- a/cmem_plugin_reason/utils.py +++ b/cmem_plugin_reason/utils.py @@ -230,7 +230,7 @@ def post_profiles(plugin: WorkflowPlugin, valid_profiles: list) -> None: query = f""" INSERT DATA {{ GRAPH <{plugin.output_graph_iri}> {{ - <{plugin.ontology_graph_iri}> + <{plugin.ontology_graph_iri}> a ; "{profiles}" . }} }} diff --git a/tests/test_elk.ttl b/tests/test_elk.ttl index d848de9..209378b 100644 --- a/tests/test_elk.ttl +++ b/tests/test_elk.ttl @@ -126,5 +126,6 @@ vocab:pet_owner . -vocab: "DL" , "Full" . +vocab: a owl:Ontology ; + "DL" , "Full" . diff --git a/tests/test_emr.ttl b/tests/test_emr.ttl index 8a0f1f2..2efbc00 100644 --- a/tests/test_emr.ttl +++ b/tests/test_emr.ttl @@ -126,4 +126,5 @@ vocab:pet_owner . -vocab: "DL" , "Full" . +vocab: a owl:Ontology ; + "DL" , "Full" . diff --git a/tests/test_hermit.ttl b/tests/test_hermit.ttl index 173d935..54086b8 100644 --- a/tests/test_hermit.ttl +++ b/tests/test_hermit.ttl @@ -194,4 +194,5 @@ . -vocab: "DL" , "Full" . +vocab: a owl:Ontology ; + "DL" , "Full" . diff --git a/tests/test_jfact.ttl b/tests/test_jfact.ttl index 173d935..54086b8 100644 --- a/tests/test_jfact.ttl +++ b/tests/test_jfact.ttl @@ -194,4 +194,5 @@ . -vocab: "DL" , "Full" . +vocab: a owl:Ontology ; + "DL" , "Full" . diff --git a/tests/test_reason.py b/tests/test_reason.py index ec51a21..2b86e89 100644 --- a/tests/test_reason.py +++ b/tests/test_reason.py @@ -77,9 +77,10 @@ def test_reasoner(reasoner: str, err_list: list) -> list: class_assertion=True, property_assertion=True, validate_profile=True, - ).execute((), context=TestExecutionContext()) + ).execute(None, context=TestExecutionContext()) result = get_remote_graph(REASON_RESULT_GRAPH_IRI) + result.serialize(f"temp/{reasoner}.ttl", format="turtle") test = Graph().parse(Path(__path__[0]) / f"test_{reasoner}.ttl", format="turtle") if to_isomorphic(result) != to_isomorphic(test): err_list.append(reasoner) @@ -91,7 +92,7 @@ def test_validate(errors: str) -> str: output_graph_iri=OUTPUT_GRAPH_IRI, validate_profile=True, md_filename=MD_FILENAME, - ).execute((), context=TestExecutionContext(PROJECT_ID)) + ).execute(None, context=TestExecutionContext(PROJECT_ID)) val_errors = "" md_test = (Path(__path__[0]) / "test_validate.md").read_text() @@ -99,8 +100,8 @@ def test_validate(errors: str) -> str: if next(iter(result.entities)).values[0][0] != md_test: # type: ignore[union-attr] val_errors += 'EntityPath "markdown" output error. ' - if next(iter(result.entities)).values[2] != ["Full", "DL", "EL", "QL", "RL"]: # type: ignore[union-attr] - val_errors += 'EntityPath "profile" output error. ' + if next(iter(result.entities)).values[2][0] != "Full,DL,EL,QL,RL": # type: ignore[union-attr] + val_errors += 'EntityPath "valid_profile" output error. ' if md_test != get_resource(PROJECT_ID, MD_FILENAME).decode(): val_errors += "Markdown file error. " diff --git a/tests/test_structural.ttl b/tests/test_structural.ttl index df51dc2..339878e 100644 --- a/tests/test_structural.ttl +++ b/tests/test_structural.ttl @@ -97,4 +97,5 @@ vocab:animal . -vocab: "DL" , "Full" . +vocab: a owl:Ontology ; + "DL" , "Full" . diff --git a/tests/test_validate_output.ttl b/tests/test_validate_output.ttl index e2fb07a..cec5c12 100644 --- a/tests/test_validate_output.ttl +++ b/tests/test_validate_output.ttl @@ -18,5 +18,6 @@ a owl:Class . - "Full", "DL", "EL", "QL", "RL" . + a owl:Ontology ; + "Full", "DL", "EL", "QL", "RL" . diff --git a/tests/test_whelk.ttl b/tests/test_whelk.ttl index 4341388..ea179a4 100644 --- a/tests/test_whelk.ttl +++ b/tests/test_whelk.ttl @@ -188,4 +188,5 @@ . -vocab: "DL" , "Full" . +vocab: a owl:Ontology ; + "DL" , "Full" . From a3ce2ba32bb60bc7b936be6865fd4eda95cca5ff Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Mon, 12 Aug 2024 14:10:00 +0100 Subject: [PATCH 21/32] edit readme --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9bde745..831ec31 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,8 @@ Maximum heap size for the Java virtual machine in the DI container running the r # Validate The plugin outputs the explanation as text in Markdown format on the path "markdown", -the ontology IRI on the path "ontology", and (if enabled) the valid OWL2 profiles in the path "profile". +the ontology IRI on the path "ontology_graph_iri", and (if enabled) the valid OWL2 profiles on the path "valid_profiles" as +a comma-separated string. ## Options From 31270c182ce2f10255f554f2ee3db00bc0c9d897 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Mon, 12 Aug 2024 14:15:00 +0100 Subject: [PATCH 22/32] fix test --- tests/test_reason.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_reason.py b/tests/test_reason.py index 2b86e89..d4d2587 100644 --- a/tests/test_reason.py +++ b/tests/test_reason.py @@ -80,7 +80,6 @@ def test_reasoner(reasoner: str, err_list: list) -> list: ).execute(None, context=TestExecutionContext()) result = get_remote_graph(REASON_RESULT_GRAPH_IRI) - result.serialize(f"temp/{reasoner}.ttl", format="turtle") test = Graph().parse(Path(__path__[0]) / f"test_{reasoner}.ttl", format="turtle") if to_isomorphic(result) != to_isomorphic(test): err_list.append(reasoner) @@ -101,7 +100,7 @@ def test_validate(errors: str) -> str: val_errors += 'EntityPath "markdown" output error. ' if next(iter(result.entities)).values[2][0] != "Full,DL,EL,QL,RL": # type: ignore[union-attr] - val_errors += 'EntityPath "valid_profile" output error. ' + val_errors += 'EntityPath "valid_profiles" output error. ' if md_test != get_resource(PROJECT_ID, MD_FILENAME).decode(): val_errors += "Markdown file error. " From 5a760d61d62df8aa0539cfdf2dd43251d2807b80 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Mon, 12 Aug 2024 14:34:07 +0100 Subject: [PATCH 23/32] remove unused method --- cmem_plugin_reason/plugin_reason.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index e56eebc..12cb3b5 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -11,7 +11,6 @@ from cmem.cmempy.dp.proxy.graph import get from cmem_plugin_base.dataintegration.context import ExecutionContext, ExecutionReport from cmem_plugin_base.dataintegration.description import Icon, Plugin, PluginParameter -from cmem_plugin_base.dataintegration.entity import EntityPath, EntitySchema from cmem_plugin_base.dataintegration.parameter.choice import ChoiceParameterType from cmem_plugin_base.dataintegration.parameter.graph import GraphParameterType from cmem_plugin_base.dataintegration.plugins import WorkflowPlugin @@ -271,13 +270,6 @@ def __init__( # noqa: PLR0913, C901 self.input_ports = FixedNumberOfInputs([]) self.output_port = None - def generate_input_schema(self) -> EntitySchema: - """Generate the output schema.""" - return EntitySchema( - type_uri="validate", - paths=[EntityPath("profile"), EntityPath("ontology")], - ) - def get_graphs(self, graphs: dict, context: ExecutionContext) -> None: """Get graphs from CMEM""" for iri, filename in graphs.items(): From d8c3d4039b4449ff65c7621bf4cf71f7d1ae4576 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Mon, 12 Aug 2024 16:12:57 +0100 Subject: [PATCH 24/32] verify valid_profiles input --- cmem_plugin_reason/plugin_reason.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index 12cb3b5..32682f1 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -250,6 +250,14 @@ def __init__( # noqa: PLR0913, C901 errors += 'Invalid value for parameter "Reasoner". ' if True not in self.axioms.values(): errors += "No axiom generator selected. " + if ( + input_profiles + and valid_profiles + and not set(valid_profiles.lower().split(",")).issubset( + ["full", "dl", "el", "ql", "rl"] + ) + ): + errors += "Invalid value for valid profiles input. " if max_ram_percentage not in range(1, 101): errors += 'Invalid value for parameter "Maximum RAM Percentage". ' if errors: From 304abf7b50c61ff3fbe44f95500772969fed9776 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Tue, 13 Aug 2024 14:15:38 +0100 Subject: [PATCH 25/32] add parameters for owl:imports and entity output. PLugin doc imported from md files --- CHANGELOG.md | 2 + cmem_plugin_reason/plugin_reason.py | 65 ++++++++++++++++++------ cmem_plugin_reason/plugin_validate.py | 35 +++++++++---- cmem_plugin_reason/reason_doc.md | 72 +++++++++++++++++++++++++++ cmem_plugin_reason/utils.py | 6 +++ cmem_plugin_reason/validate_doc.md | 54 ++++++++++++++++++++ 6 files changed, 209 insertions(+), 25 deletions(-) create mode 100644 cmem_plugin_reason/reason_doc.md create mode 100644 cmem_plugin_reason/validate_doc.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a39aa0..709cf2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ### Added - defined input and output schema + - Reason: parameters to import the result graph in the ontology graph and to import the ontology graph in the result graph + - Validate: parameter to enable/disable entity output ### Fixed diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index 32682f1..42ac7d1 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -9,6 +9,7 @@ import validators.url from cmem.cmempy.dp.proxy.graph import get +from cmem.cmempy.dp.proxy.update import post from cmem_plugin_base.dataintegration.context import ExecutionContext, ExecutionReport from cmem_plugin_base.dataintegration.description import Icon, Plugin, PluginParameter from cmem_plugin_base.dataintegration.parameter.choice import ChoiceParameterType @@ -25,6 +26,7 @@ MAX_RAM_PERCENTAGE_PARAMETER, ONTOLOGY_GRAPH_IRI_PARAMETER, OUTPUT_GRAPH_IRI_PARAMETER, + REASON_DOC, REASONERS, VALIDATE_PROFILES_PARAMETER, create_xml_catalog_file, @@ -45,9 +47,7 @@ label="Reason", icon=Icon(file_name="fluent--brain-circuit-24-regular.svg", package=__package__), description="Performs OWL reasoning.", - documentation="""A task performing OWL reasoning. With an OWL ontology and a data graph as input - the reasoning result is written to a specified graph. The following reasoners are supported: - ELK, Expression Materializing Reasoner, HermiT, JFact, Structural Reasoner and Whelk.""", + documentation=REASON_DOC, parameters=[ ONTOLOGY_GRAPH_IRI_PARAMETER, OUTPUT_GRAPH_IRI_PARAMETER, @@ -181,6 +181,22 @@ default_value=False, advanced=True, ), + PluginParameter( + param_type=BoolParameterType(), + name="import_ontology", + label="Add ontology graph import to result graph.", + description="""Add the triple owl:imports to the + output graph.""", + default_value=True, + ), + PluginParameter( + param_type=BoolParameterType(), + name="import_result", + label="Add result graph import to ontology graph.", + description="""Add the triple owl:imports to the + ontology graph.""", + default_value=False, + ), PluginParameter( param_type=StringParameterType(), name="valid_profiles", @@ -215,6 +231,8 @@ def __init__( # noqa: PLR0913, C901 sub_data_property: bool = False, sub_object_property: bool = False, validate_profile: bool = False, + import_ontology: bool = True, + import_result: bool = False, input_profiles: bool = False, max_ram_percentage: int = MAX_RAM_PERCENTAGE_DEFAULT, valid_profiles: str = "", @@ -250,6 +268,11 @@ def __init__( # noqa: PLR0913, C901 errors += 'Invalid value for parameter "Reasoner". ' if True not in self.axioms.values(): errors += "No axiom generator selected. " + if import_result and import_ontology: + errors += ( + 'Enable only one of "Add result graph import to ontology graph" and "Add ' + 'ontology graph import to result graph". ' + ) if ( input_profiles and valid_profiles @@ -268,6 +291,8 @@ def __init__( # noqa: PLR0913, C901 self.output_graph_iri = output_graph_iri self.reasoner = reasoner self.validate_profile = validate_profile + self.import_ontology = import_ontology + self.import_result = import_result self.input_profiles = input_profiles self.max_ram_percentage = max_ram_percentage self.valid_profiles = valid_profiles @@ -285,25 +310,20 @@ def get_graphs(self, graphs: dict, context: ExecutionContext) -> None: with (Path(self.temp) / filename).open("w", encoding="utf-8") as file: setup_cmempy_user_access(context.user) for line in get(iri).text.splitlines(): - if line != ( - f"<{iri}> " - f"<{self.output_graph_iri}> ." + if not line.endswith( + f" <{self.output_graph_iri}> ." ): file.write(line + "\n") - if iri == self.data_graph_iri: - file.write( - f"<{iri}> " - f"<{self.ontology_graph_iri}> ." - ) def reason(self, graphs: dict) -> None: """Reason""" axioms = " ".join(k for k, v in self.axioms.items() if v) data_location = f"{self.temp}/{graphs[self.data_graph_iri]}" + ontology_location = f"{self.temp}/{graphs[self.ontology_graph_iri]}" utctime = str(datetime.fromtimestamp(int(time()), tz=UTC))[:-6].replace(" ", "T") + "Z" cmd = ( - f'reason --input "{data_location}" ' - f"--reasoner {self.reasoner} " + f'merge --input "{data_location}" --input "{ontology_location}" ' + f"reason --reasoner {self.reasoner} " f'--axiom-generators "{axioms}" ' f"--include-indirect true " f"--exclude-duplicate-axioms true " @@ -321,8 +341,10 @@ def reason(self, graphs: dict) -> None: f'--link-annotation dc:source "{self.data_graph_iri}" ' f'--link-annotation dc:source "{self.ontology_graph_iri}" ' f'--typed-annotation dc:created "{utctime}" xsd:dateTime ' - f'--output "{self.temp}/result.ttl"' ) + if self.import_ontology: + cmd += f'--link-annotation owl:imports "{self.ontology_graph_iri}" ' + cmd += f'--output "{self.temp}/result.ttl"' response = robot(cmd, self.max_ram_percentage) if response.returncode != 0: if response.stdout: @@ -331,6 +353,18 @@ def reason(self, graphs: dict) -> None: raise OSError(response.stderr.decode()) raise OSError("ROBOT error") + def add_result_import(self) -> None: + """Add result graph import to ontology graph""" + query = f""" + INSERT DATA {{ + GRAPH <{self.ontology_graph_iri}> {{ + <{self.ontology_graph_iri}> + <{self.output_graph_iri}> + }} + }} + """ + post(query=query) + def _execute(self, context: ExecutionContext) -> None: """`Execute plugin""" setup_cmempy_user_access(context.user) @@ -349,6 +383,9 @@ def _execute(self, context: ExecutionContext) -> None: valid_profiles = validate_profiles(self, graphs) post_profiles(self, valid_profiles) post_provenance(self, get_provenance(self, context)) + if self.import_result: + setup_cmempy_user_access(context.user) + self.add_result_import() context.report.update( ExecutionReport( diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index be185a9..46f75b8 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -27,6 +27,7 @@ ONTOLOGY_GRAPH_IRI_PARAMETER, OUTPUT_GRAPH_IRI_PARAMETER, REASONERS, + VALIDATE_DOC, VALIDATE_PROFILES_PARAMETER, create_xml_catalog_file, get_graphs_tree, @@ -45,11 +46,7 @@ @Plugin( label="Validate OWL consistency", description="Validates the consistency of an OWL ontology.", - documentation="""A task validating the consistency of an OWL ontology and generating an - explanation if inconsistencies are found. The explanation can be written to the project as a - Markdown file and/or to a specified graph. The Markdown string is also provided as an output - entity using the path "text". The following reasoners are supported: ELK, Expression - Materializing Reasoner, HermiT, JFact, Structural Reasoner and Whelk.""", + documentation=VALIDATE_DOC, icon=Icon(file_name="file-icons--owl.svg", package=__package__), parameters=[ ONTOLOGY_GRAPH_IRI_PARAMETER, @@ -78,6 +75,15 @@ "not output entities.", default_value=False, ), + PluginParameter( + param_type=BoolParameterType(), + name="output_entities", + label="Output entities", + description="""Output entities. The plugin outputs the explanation as text in Markdown + format on the path "markdown", the ontology IRI on the path "ontology_graph_iri", and, + if enabled, the valid OWL2 profiles on the path "valid_profiles".""", + default_value=False, + ), ], ) class ValidatePlugin(WorkflowPlugin): @@ -90,6 +96,7 @@ def __init__( # noqa: PLR0913 output_graph_iri: str = "", md_filename: str = "", validate_profile: bool = False, + output_entities: bool = False, stop_at_inconsistencies: bool = False, max_ram_percentage: int = MAX_RAM_PERCENTAGE_DEFAULT, ) -> None: @@ -104,6 +111,8 @@ def __init__( # noqa: PLR0913 errors += 'Invalid value for parameter "Reasoner". ' if md_filename and not is_valid_filename(md_filename): errors += 'Invalid filename for parameter "Output filename". ' + if not output_graph_iri and not md_filename and not output_entities: + errors += "No output selected. " if max_ram_percentage not in range(1, 101): errors += 'Invalid value for parameter "Maximum RAM Percentage". ' if errors: @@ -119,14 +128,18 @@ def __init__( # noqa: PLR0913 self.md_filename = "mdfile.md" self.write_md = False self.validate_profile = validate_profile + self.output_entities = output_entities self.max_ram_percentage = max_ram_percentage self.input_ports = FixedNumberOfInputs([]) - self.schema = self.generate_output_schema() - self.output_port = FixedSchemaPort(self.schema) + if self.output_entities: + self.schema = self.generate_output_schema() + self.output_port = FixedSchemaPort(self.schema) + else: + self.output_port = None - def generate_output_schema(self) -> EntitySchema: - """Generate the output schema.""" + def generate_output_schema(self) -> EntitySchema | None: + """Generate output entity schema.""" paths = [EntityPath("markdown"), EntityPath("ontology_graph_iri")] if self.validate_profile: paths.append(EntityPath("valid_profiles")) @@ -243,8 +256,8 @@ def _execute(self, context: ExecutionContext) -> Entities: entity_count=1, ) ) - - return self.make_entities(text, valid_profiles) + if self.output_entities: + return self.make_entities(text, valid_profiles) def execute(self, inputs: None, context: ExecutionContext) -> Entities: # noqa: ARG002 """Remove temp files on error""" diff --git a/cmem_plugin_reason/reason_doc.md b/cmem_plugin_reason/reason_doc.md new file mode 100644 index 0000000..12a93be --- /dev/null +++ b/cmem_plugin_reason/reason_doc.md @@ -0,0 +1,72 @@ +A task performing OWL reasoning. With an OWL ontology and a data graph as input the reasoning result is written to a specified graph. + +## Options + +### Data graph IRI + +The IRI of the input data graph. The graph IRI is selected from a list of graphs of types `di:Dataset`, `void:Dataset` +and `owl:Ontology`. + +### Ontology graph IRI + +The IRI of the input ontology graph. The graph IRI is selected from a list of graphs of type`owl:Ontology`. + +### Result graph IRI + +The IRI of the output graph for the reasoning result. + +⚠️ Existing graphs will be overwritten. + +### Reasoner + +The following reasoner options are supported: +- [ELK](https://code.google.com/p/elk-reasoner/) (elk) +- [Expression Materializing Reasoner](http://static.javadoc.io/org.geneontology/expression-materializing-reasoner/0.1.3/org/geneontology/reasoner/ExpressionMaterializingReasoner.html) (emr) +- [HermiT](http://www.hermit-reasoner.com/) (hermit) +- [JFact](http://jfact.sourceforge.net/) (jfact) +- [Structural Reasoner](http://owlcs.github.io/owlapi/apidocs_4/org/semanticweb/owlapi/reasoner/structural/StructuralReasoner.html) (structural) +- [Whelk](https://github.com/balhoff/whelk) (whelk) + +### Generated Axioms + +By default, the reason operation will only assert inferred subclass axioms. The plugin provides the following +parameters to include inferred axiom generators: + +#### Class axiom generators +- SubClass +- EquivalentClass +- DisjointClasses + +#### Data property axiom generators +- DataPropertyCharacteristic +- EquivalentDataProperties +- SubDataProperty + +#### Individual axiom generators +- ClassAssertion +- PropertyAssertion + +#### Object property axiom generators +- EquivalentObjectProperty +- InverseObjectProperties +- ObjectPropertyCharacteristic +- SubObjectProperty +- ObjectPropertyRange +- ObjectPropertyDomain + +### Validate OWL2 profiles + +Validate the input ontology against OWL profiles (DL, EL, QL, RL, and Full). The ontology is annotated in the output graph. + +### Process valid OWL profiles from input + +If enabled along with the "Validate OWL2 profiles" parameter, the ontology IRI and list of valid profiles is taken from the config port input, +without validating the ontology against the profiles in the plugin. If the "Validate OWL2 profiles" parameter is enabled in the "Validate" plugin, it can be directly connected to the input +of the "Reason" plugin. + + +### Maximum RAM Percentage + +Maximum heap size for the Java virtual machine in the DI container running the reasoning process. + +⚠️ Setting the percentage too high may result in an out of memory error. diff --git a/cmem_plugin_reason/utils.py b/cmem_plugin_reason/utils.py index ab276a8..17b7dfb 100644 --- a/cmem_plugin_reason/utils.py +++ b/cmem_plugin_reason/utils.py @@ -20,6 +20,12 @@ from . import __path__ +with (Path(__path__[0]) / "reason_doc.md").open("r") as f: + REASON_DOC = f.read() + +with (Path(__path__[0]) / "validate_doc.md").open("r") as f: + VALIDATE_DOC = f.read() + REASONERS = OrderedDict( { "elk": "ELK", diff --git a/cmem_plugin_reason/validate_doc.md b/cmem_plugin_reason/validate_doc.md new file mode 100644 index 0000000..91e2871 --- /dev/null +++ b/cmem_plugin_reason/validate_doc.md @@ -0,0 +1,54 @@ +A task validating the consistency of an OWL ontology and generating an explanation if inconsistencies are found. +The plugin outputs the explanation as text in Markdown format on the path "markdown", the ontology IRI on the path +"ontology_graph_iri", and, if enabled, the valid OWL2 profiles on the path "valid_profiles" as a comma-separated string. + +## Options + +### Ontology graph IRI + +The IRI of the input ontology graph. The graph IRI is selected from a list of graphs of type`owl:Ontology`. + +### Reasoner + +The following reasoner options are supported: +- [ELK](https://code.google.com/p/elk-reasoner/) (elk) +- [Expression Materializing Reasoner](http://static.javadoc.io/org.geneontology/expression-materializing-reasoner/0.1.3/org/geneontology/reasoner/ExpressionMaterializingReasoner.html) (emr) +- [HermiT](http://www.hermit-reasoner.com/) (hermit) +- [JFact](http://jfact.sourceforge.net/) (jfact) +- [Structural Reasoner](http://owlcs.github.io/owlapi/apidocs_4/org/semanticweb/owlapi/reasoner/structural/StructuralReasoner.html) (structural) +- [Whelk](https://github.com/balhoff/whelk) (whelk) + +### Produce output graph + +If enabled, an explanation graph is created. + +### Output graph IRI + +The IRI of the output graph for the reasoning result. + +⚠️ Existing graphs will be overwritten. + +### Write markdown explanation file + +If enabled, an explanation markdown file is written to the project. + +### Output filename + +The filename of the Markdown file with the explanation of inconsistencies. + +⚠️ Existing files will be overwritten. + +### Stop at inconsistencies +Raise an error if inconsistencies are found. If enabled, the plugin does not output entities. + +### Validate OWL2 profiles + +Validate the input ontology against OWL profiles (DL, EL, QL, RL, and Full). The valid profiles are added to the output +Markdown file and the ontology is annotated in the output graph. The plugin outputs the profiles with path "valid_profiles", +and the ontology IRI with path "ontology_graph_iri". + +### Maximum RAM Percentage + +Maximum heap size for the Java virtual machine in the DI container running the reasoning process. + +⚠️ Setting the percentage too high may result in an out of memory error. From 7cb5c8737e3589dc02188afd0b12e42e79ffcb8c Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Tue, 13 Aug 2024 15:18:08 +0100 Subject: [PATCH 26/32] fix tests --- cmem_plugin_reason/plugin_reason.py | 36 ++++++++++++++++++++------- cmem_plugin_reason/plugin_validate.py | 7 +++--- tests/test_reason.py | 2 ++ 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index 42ac7d1..39ce138 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -210,7 +210,7 @@ class ReasonPlugin(WorkflowPlugin): """Reason plugin""" - def __init__( # noqa: PLR0913, C901 + def __init__( # noqa: PLR0913 C901 self, data_graph_iri: str = "", ontology_graph_iri: str = "", @@ -314,16 +314,20 @@ def get_graphs(self, graphs: dict, context: ExecutionContext) -> None: f" <{self.output_graph_iri}> ." ): file.write(line + "\n") + if iri == self.data_graph_iri: + file.write( + f"\n<{iri}> " + f" <{self.ontology_graph_iri}> ." + ) def reason(self, graphs: dict) -> None: """Reason""" axioms = " ".join(k for k, v in self.axioms.items() if v) data_location = f"{self.temp}/{graphs[self.data_graph_iri]}" - ontology_location = f"{self.temp}/{graphs[self.ontology_graph_iri]}" utctime = str(datetime.fromtimestamp(int(time()), tz=UTC))[:-6].replace(" ", "T") + "Z" cmd = ( - f'merge --input "{data_location}" --input "{ontology_location}" ' - f"reason --reasoner {self.reasoner} " + f'reason --input "{data_location}" ' + f"--reasoner {self.reasoner} " f'--axiom-generators "{axioms}" ' f"--include-indirect true " f"--exclude-duplicate-axioms true " @@ -341,10 +345,8 @@ def reason(self, graphs: dict) -> None: f'--link-annotation dc:source "{self.data_graph_iri}" ' f'--link-annotation dc:source "{self.ontology_graph_iri}" ' f'--typed-annotation dc:created "{utctime}" xsd:dateTime ' + f'--output "{self.temp}/result.ttl"' ) - if self.import_ontology: - cmd += f'--link-annotation owl:imports "{self.ontology_graph_iri}" ' - cmd += f'--output "{self.temp}/result.ttl"' response = robot(cmd, self.max_ram_percentage) if response.returncode != 0: if response.stdout: @@ -365,6 +367,18 @@ def add_result_import(self) -> None: """ post(query=query) + def remove_ontology_import(self) -> None: + """Add result graph import to ontology graph""" + query = f""" + DELETE DATA {{ + GRAPH <{self.output_graph_iri}> {{ + <{self.output_graph_iri}> + <{self.ontology_graph_iri}> + }} + }} + """ + post(query=query) + def _execute(self, context: ExecutionContext) -> None: """`Execute plugin""" setup_cmempy_user_access(context.user) @@ -383,9 +397,13 @@ def _execute(self, context: ExecutionContext) -> None: valid_profiles = validate_profiles(self, graphs) post_profiles(self, valid_profiles) post_provenance(self, get_provenance(self, context)) - if self.import_result: + + if self.import_result or not self.import_ontology: setup_cmempy_user_access(context.user) - self.add_result_import() + if self.import_result: + self.add_result_import() + if not self.import_ontology: + self.remove_ontology_import() context.report.update( ExecutionReport( diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index 46f75b8..c81dc8f 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -89,7 +89,7 @@ class ValidatePlugin(WorkflowPlugin): """Validate plugin""" - def __init__( # noqa: PLR0913 + def __init__( # noqa: PLR0913 C901 self, ontology_graph_iri: str = "", reasoner: str = "elk", @@ -213,7 +213,7 @@ def make_entities(self, text: str, valid_profiles: list) -> Entities: ] return Entities(entities=entities, schema=self.schema) - def _execute(self, context: ExecutionContext) -> Entities: + def _execute(self, context: ExecutionContext) -> Entities | None: """Run the workflow operator.""" setup_cmempy_user_access(context.user) graphs = get_graphs_tree((self.ontology_graph_iri, self.output_graph_iri)) @@ -258,8 +258,9 @@ def _execute(self, context: ExecutionContext) -> Entities: ) if self.output_entities: return self.make_entities(text, valid_profiles) + return None - def execute(self, inputs: None, context: ExecutionContext) -> Entities: # noqa: ARG002 + def execute(self, inputs: None, context: ExecutionContext) -> Entities | None: # noqa: ARG002 """Remove temp files on error""" context.report.update( ExecutionReport( diff --git a/tests/test_reason.py b/tests/test_reason.py index d4d2587..e03d807 100644 --- a/tests/test_reason.py +++ b/tests/test_reason.py @@ -77,6 +77,7 @@ def test_reasoner(reasoner: str, err_list: list) -> list: class_assertion=True, property_assertion=True, validate_profile=True, + import_ontology=True, ).execute(None, context=TestExecutionContext()) result = get_remote_graph(REASON_RESULT_GRAPH_IRI) @@ -91,6 +92,7 @@ def test_validate(errors: str) -> str: output_graph_iri=OUTPUT_GRAPH_IRI, validate_profile=True, md_filename=MD_FILENAME, + output_entities=True, ).execute(None, context=TestExecutionContext(PROJECT_ID)) val_errors = "" From f3107f1fef949cf4b9b3bec4cfaeee0abefb3ee5 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Wed, 14 Aug 2024 16:34:19 +0100 Subject: [PATCH 27/32] edit docs --- README.md | 27 ++++++++++++++++++++------- cmem_plugin_reason/plugin_reason.py | 12 ++++++------ cmem_plugin_reason/reason_doc.md | 20 +++++++++++++++----- cmem_plugin_reason/validate_doc.md | 11 +++++++---- 4 files changed, 48 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 831ec31..d7697a3 100644 --- a/README.md +++ b/README.md @@ -84,14 +84,24 @@ parameters to include inferred axiom generators: ### Validate OWL2 profiles -Validate the input ontology against OWL profiles (DL, EL, QL, RL, and Full). The ontology is annotated in the output graph. +Validate the input ontology against OWL profiles (DL, EL, QL, RL, and Full) and annotate the result graph. ### Process valid OWL profiles from input -If enabled along with the "Validate OWL2 profiles" parameter, the ontology IRI and list of valid profiles is taken from the config port input, -without validating the ontology against the profiles in the plugin. If the "Validate OWL2 profiles" parameter is enabled in the "Validate" plugin, it can be directly connected to the input -of the "Reason" plugin. +If enabled along with the "Validate OWL2 profiles" parameter, the valid profiles and ontology IRI is taken from the +config port input (parameters "valid_profiles" and "ontology_graph_iri") instead of from running the validation in the +plugin. The valid profiles input is a comma-separated string (e.g. "Full,DL").the ontology IRI and list of valid +profiles is taken from the config port input, without validating the ontology against the profiles in the plugin. If the +"Validate OWL2 profiles" parameter is enabled in the "Validate" plugin, it can be directly connected to the input of the +"Reason" plugin. +### Add ontology graph import to result graph + +Add the triple ` owl:imports ` to the output graph. + +### Add result graph import to ontology graph + +Add the triple ` owl:imports ` to the ontology graph ### Maximum RAM Percentage @@ -146,9 +156,12 @@ Raise an error if inconsistencies are found. If enabled, the plugin does not out ### Validate OWL2 profiles -Validate the input ontology against OWL profiles (DL, EL, QL, RL, and Full). The valid profiles are added to the output -Markdown file and the ontology is annotated in the output graph. The plugin outputs the profiles with path "profile", -and the ontology IRI with path "ontology". +Validate the input ontology against OWL profiles (DL, EL, QL, RL, and Full) and annotate the result graph. + +### Output entities + +Output entities. The plugin outputs the explanation as text in Markdown format on the path "markdown", the ontology IRI +on the path "ontology_graph_iri", and, if enabled, the valid OWL2 profiles on the path "valid_profiles ### Maximum RAM Percentage diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index 39ce138..bf4d0fd 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -174,10 +174,10 @@ param_type=BoolParameterType(), name="input_profiles", label="Process valid OWL profiles from input", - description="""If the "validate OWL profiles" parameter is enabled, the valid profiles - and ontology IRI is taken from the config port input (parameters "valid_profiles" and - "ontology_graph_iri") instead of from running the validation in the plugin. The valid - profiles input is a comma-separated string (e.g. "Full,DL").""", + description="""If enabled along with the "Validate OWL2 profiles" parameter, the valid + profiles and ontology IRI is taken from the config port input (parameters + "valid_profiles" and "ontology_graph_iri") instead of from running the validation in the + plugin. The valid profiles input is a comma-separated string (e.g. "Full,DL").""", default_value=False, advanced=True, ), @@ -316,7 +316,7 @@ def get_graphs(self, graphs: dict, context: ExecutionContext) -> None: file.write(line + "\n") if iri == self.data_graph_iri: file.write( - f"\n<{iri}> " + f"<{iri}> " f" <{self.ontology_graph_iri}> ." ) @@ -368,7 +368,7 @@ def add_result_import(self) -> None: post(query=query) def remove_ontology_import(self) -> None: - """Add result graph import to ontology graph""" + """remove ontology graph import from output graph""" query = f""" DELETE DATA {{ GRAPH <{self.output_graph_iri}> {{ diff --git a/cmem_plugin_reason/reason_doc.md b/cmem_plugin_reason/reason_doc.md index 12a93be..a28ccf9 100644 --- a/cmem_plugin_reason/reason_doc.md +++ b/cmem_plugin_reason/reason_doc.md @@ -56,17 +56,27 @@ parameters to include inferred axiom generators: ### Validate OWL2 profiles -Validate the input ontology against OWL profiles (DL, EL, QL, RL, and Full). The ontology is annotated in the output graph. +Validate the input ontology against OWL profiles (DL, EL, QL, RL, and Full) and annotate the result graph. ### Process valid OWL profiles from input -If enabled along with the "Validate OWL2 profiles" parameter, the ontology IRI and list of valid profiles is taken from the config port input, -without validating the ontology against the profiles in the plugin. If the "Validate OWL2 profiles" parameter is enabled in the "Validate" plugin, it can be directly connected to the input -of the "Reason" plugin. +If enabled along with the "Validate OWL2 profiles" parameter, the valid profiles and ontology IRI is taken from the +config port input (parameters "valid_profiles" and "ontology_graph_iri") instead of from running the validation in the +plugin. The valid profiles input is a comma-separated string (e.g. "Full,DL").the ontology IRI and list of valid +profiles is taken from the config port input, without validating the ontology against the profiles in the plugin. If the +"Validate OWL2 profiles" parameter is enabled in the "Validate" plugin, it can be directly connected to the input of the +"Reason" plugin. +### Add ontology graph import to result graph + +Add the triple ` owl:imports ` to the output graph. + +### Add result graph import to ontology graph + +Add the triple ` owl:imports ` to the ontology graph ### Maximum RAM Percentage Maximum heap size for the Java virtual machine in the DI container running the reasoning process. -⚠️ Setting the percentage too high may result in an out of memory error. +:warning: Setting the percentage too high may result in an out of memory error. diff --git a/cmem_plugin_reason/validate_doc.md b/cmem_plugin_reason/validate_doc.md index 91e2871..055a46b 100644 --- a/cmem_plugin_reason/validate_doc.md +++ b/cmem_plugin_reason/validate_doc.md @@ -43,12 +43,15 @@ Raise an error if inconsistencies are found. If enabled, the plugin does not out ### Validate OWL2 profiles -Validate the input ontology against OWL profiles (DL, EL, QL, RL, and Full). The valid profiles are added to the output -Markdown file and the ontology is annotated in the output graph. The plugin outputs the profiles with path "valid_profiles", -and the ontology IRI with path "ontology_graph_iri". +Validate the input ontology against OWL profiles (DL, EL, QL, RL, and Full) and annotate the result graph. + +### Output entities + +Output entities. The plugin outputs the explanation as text in Markdown format on the path "markdown", the ontology IRI +on the path "ontology_graph_iri", and, if enabled, the valid OWL2 profiles on the path "valid_profiles ### Maximum RAM Percentage Maximum heap size for the Java virtual machine in the DI container running the reasoning process. -⚠️ Setting the percentage too high may result in an out of memory error. +:warning: Setting the percentage too high may result in an out of memory error. From ddd3a8b61c7263c12b7e7019705141169185465c Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Wed, 14 Aug 2024 16:38:33 +0100 Subject: [PATCH 28/32] edit doc --- README.md | 5 +---- cmem_plugin_reason/plugin_reason.py | 2 +- cmem_plugin_reason/reason_doc.md | 5 +---- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d7697a3..ea9783a 100644 --- a/README.md +++ b/README.md @@ -90,10 +90,7 @@ Validate the input ontology against OWL profiles (DL, EL, QL, RL, and Full) and If enabled along with the "Validate OWL2 profiles" parameter, the valid profiles and ontology IRI is taken from the config port input (parameters "valid_profiles" and "ontology_graph_iri") instead of from running the validation in the -plugin. The valid profiles input is a comma-separated string (e.g. "Full,DL").the ontology IRI and list of valid -profiles is taken from the config port input, without validating the ontology against the profiles in the plugin. If the -"Validate OWL2 profiles" parameter is enabled in the "Validate" plugin, it can be directly connected to the input of the -"Reason" plugin. +plugin. The valid profiles input is a comma-separated string (e.g. "Full,DL"). ### Add ontology graph import to result graph diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index bf4d0fd..f78085f 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -368,7 +368,7 @@ def add_result_import(self) -> None: post(query=query) def remove_ontology_import(self) -> None: - """remove ontology graph import from output graph""" + """Remove ontology graph import from output graph""" query = f""" DELETE DATA {{ GRAPH <{self.output_graph_iri}> {{ diff --git a/cmem_plugin_reason/reason_doc.md b/cmem_plugin_reason/reason_doc.md index a28ccf9..e5a58b4 100644 --- a/cmem_plugin_reason/reason_doc.md +++ b/cmem_plugin_reason/reason_doc.md @@ -62,10 +62,7 @@ Validate the input ontology against OWL profiles (DL, EL, QL, RL, and Full) and If enabled along with the "Validate OWL2 profiles" parameter, the valid profiles and ontology IRI is taken from the config port input (parameters "valid_profiles" and "ontology_graph_iri") instead of from running the validation in the -plugin. The valid profiles input is a comma-separated string (e.g. "Full,DL").the ontology IRI and list of valid -profiles is taken from the config port input, without validating the ontology against the profiles in the plugin. If the -"Validate OWL2 profiles" parameter is enabled in the "Validate" plugin, it can be directly connected to the input of the -"Reason" plugin. +plugin. The valid profiles input is a comma-separated string (e.g. "Full,DL"). ### Add ontology graph import to result graph From 984c880dc42ded086bad056b6e95157871575ca0 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Wed, 14 Aug 2024 16:42:37 +0100 Subject: [PATCH 29/32] edit doc --- cmem_plugin_reason/reason_doc.md | 2 +- cmem_plugin_reason/validate_doc.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmem_plugin_reason/reason_doc.md b/cmem_plugin_reason/reason_doc.md index e5a58b4..f6a7b09 100644 --- a/cmem_plugin_reason/reason_doc.md +++ b/cmem_plugin_reason/reason_doc.md @@ -76,4 +76,4 @@ Add the triple ` owl:imports ` to the onto Maximum heap size for the Java virtual machine in the DI container running the reasoning process. -:warning: Setting the percentage too high may result in an out of memory error. +⚠️ Setting the percentage too high may result in an out of memory error. diff --git a/cmem_plugin_reason/validate_doc.md b/cmem_plugin_reason/validate_doc.md index 055a46b..b21df69 100644 --- a/cmem_plugin_reason/validate_doc.md +++ b/cmem_plugin_reason/validate_doc.md @@ -54,4 +54,4 @@ on the path "ontology_graph_iri", and, if enabled, the valid OWL2 profiles on th Maximum heap size for the Java virtual machine in the DI container running the reasoning process. -:warning: Setting the percentage too high may result in an out of memory error. +⚠️ Setting the percentage too high may result in an out of memory error. From 3fa14081ff85710891b070baae5665494e4caf00 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Wed, 14 Aug 2024 17:55:52 +0100 Subject: [PATCH 30/32] edit parameters --- cmem_plugin_reason/plugin_reason.py | 32 +++++++++++++++++---------- cmem_plugin_reason/plugin_validate.py | 28 ++++++++++++++++------- cmem_plugin_reason/utils.py | 15 ------------- poetry.lock | 16 +++++++------- pyproject.toml | 1 - tests/test_reason.py | 1 + 6 files changed, 49 insertions(+), 44 deletions(-) diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index f78085f..1144e72 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -5,7 +5,6 @@ from pathlib import Path from tempfile import TemporaryDirectory from time import time -from warnings import simplefilter import validators.url from cmem.cmempy.dp.proxy.graph import get @@ -19,13 +18,11 @@ from cmem_plugin_base.dataintegration.types import BoolParameterType, StringParameterType from cmem_plugin_base.dataintegration.utils import setup_cmempy_user_access from inflection import underscore -from urllib3.exceptions import InsecureRequestWarning from cmem_plugin_reason.utils import ( MAX_RAM_PERCENTAGE_DEFAULT, MAX_RAM_PERCENTAGE_PARAMETER, ONTOLOGY_GRAPH_IRI_PARAMETER, - OUTPUT_GRAPH_IRI_PARAMETER, REASON_DOC, REASONERS, VALIDATE_PROFILES_PARAMETER, @@ -40,7 +37,6 @@ ) environ["SSL_VERIFY"] = "false" -simplefilter("ignore", category=InsecureRequestWarning) @Plugin( @@ -50,15 +46,27 @@ documentation=REASON_DOC, parameters=[ ONTOLOGY_GRAPH_IRI_PARAMETER, - OUTPUT_GRAPH_IRI_PARAMETER, VALIDATE_PROFILES_PARAMETER, MAX_RAM_PERCENTAGE_PARAMETER, + PluginParameter( + param_type=GraphParameterType( + allow_only_autocompleted_values=False, + classes=[ + "https://vocab.eccenca.com/di/Dataset", + "http://rdfs.org/ns/void#Dataset", + "http://www.w3.org/2002/07/owl#Ontology", + ], + ), + name="output_graph_iri", + label="Output graph IRI", + description="""The IRI of the output graph for the inconsistency validation. ⚠️ Existing + graphs will be overwritten.""", + ), PluginParameter( param_type=ChoiceParameterType(REASONERS), name="reasoner", label="Reasoner", description="Reasoner option. Additionally, select axiom generators below.", - default_value="", ), PluginParameter( param_type=GraphParameterType( @@ -212,10 +220,10 @@ class ReasonPlugin(WorkflowPlugin): def __init__( # noqa: PLR0913 C901 self, - data_graph_iri: str = "", - ontology_graph_iri: str = "", - output_graph_iri: str = "", - reasoner: str = "", + data_graph_iri: str, + ontology_graph_iri: str, + output_graph_iri: str, + reasoner: str, class_assertion: bool = False, data_property_characteristic: bool = False, disjoint_classes: bool = False, @@ -260,9 +268,9 @@ def __init__( # noqa: PLR0913 C901 errors += 'Invalid IRI for parameter "Ontology graph IRI". ' if not validators.url(output_graph_iri): errors += 'Invalid IRI for parameter "Result graph IRI". ' - if output_graph_iri and output_graph_iri == data_graph_iri: + if output_graph_iri == data_graph_iri: errors += "Result graph IRI cannot be the same as the data graph IRI. " - if output_graph_iri and output_graph_iri == ontology_graph_iri: + if output_graph_iri == ontology_graph_iri: errors += "Result graph IRI cannot be the same as the ontology graph IRI. " if reasoner not in REASONERS: errors += 'Invalid value for parameter "Reasoner". ' diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index c81dc8f..b0d127b 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -5,7 +5,6 @@ from pathlib import Path from tempfile import TemporaryDirectory from time import time -from warnings import simplefilter import validators.url from cmem.cmempy.dp.proxy.graph import get @@ -14,18 +13,17 @@ from cmem_plugin_base.dataintegration.description import Icon, Plugin, PluginParameter from cmem_plugin_base.dataintegration.entity import Entities, Entity, EntityPath, EntitySchema from cmem_plugin_base.dataintegration.parameter.choice import ChoiceParameterType +from cmem_plugin_base.dataintegration.parameter.graph import GraphParameterType from cmem_plugin_base.dataintegration.plugins import WorkflowPlugin from cmem_plugin_base.dataintegration.ports import FixedNumberOfInputs, FixedSchemaPort from cmem_plugin_base.dataintegration.types import BoolParameterType, StringParameterType from cmem_plugin_base.dataintegration.utils import setup_cmempy_user_access from pathvalidate import is_valid_filename -from urllib3.exceptions import InsecureRequestWarning from cmem_plugin_reason.utils import ( MAX_RAM_PERCENTAGE_DEFAULT, MAX_RAM_PERCENTAGE_PARAMETER, ONTOLOGY_GRAPH_IRI_PARAMETER, - OUTPUT_GRAPH_IRI_PARAMETER, REASONERS, VALIDATE_DOC, VALIDATE_PROFILES_PARAMETER, @@ -40,7 +38,6 @@ ) environ["SSL_VERIFY"] = "false" -simplefilter("ignore", category=InsecureRequestWarning) @Plugin( @@ -52,13 +49,26 @@ ONTOLOGY_GRAPH_IRI_PARAMETER, MAX_RAM_PERCENTAGE_PARAMETER, VALIDATE_PROFILES_PARAMETER, - OUTPUT_GRAPH_IRI_PARAMETER, + PluginParameter( + param_type=GraphParameterType( + allow_only_autocompleted_values=False, + classes=[ + "https://vocab.eccenca.com/di/Dataset", + "http://rdfs.org/ns/void#Dataset", + "http://www.w3.org/2002/07/owl#Ontology", + ], + ), + name="output_graph_iri", + label="Output graph IRI", + description="""The IRI of the output graph for the inconsistency validation. ⚠️ Existing + graphs will be overwritten.""", + default_value="", + ), PluginParameter( param_type=ChoiceParameterType(REASONERS), name="reasoner", label="Reasoner", description="Reasoner option.", - default_value="", ), PluginParameter( param_type=StringParameterType(), @@ -66,6 +76,7 @@ label="Output filename", description="The filename of the Markdown file with the explanation of " "inconsistencies.⚠️ Existing files will be overwritten.", + default_value="", ), PluginParameter( param_type=BoolParameterType(), @@ -91,8 +102,8 @@ class ValidatePlugin(WorkflowPlugin): def __init__( # noqa: PLR0913 C901 self, - ontology_graph_iri: str = "", - reasoner: str = "elk", + ontology_graph_iri: str, + reasoner: str, output_graph_iri: str = "", md_filename: str = "", validate_profile: bool = False, @@ -268,5 +279,6 @@ def execute(self, inputs: None, context: ExecutionContext) -> Entities | None: operation_desc="ontologies validated.", ) ) + with TemporaryDirectory() as self.temp: return self._execute(context) diff --git a/cmem_plugin_reason/utils.py b/cmem_plugin_reason/utils.py index 17b7dfb..9eeafa8 100644 --- a/cmem_plugin_reason/utils.py +++ b/cmem_plugin_reason/utils.py @@ -65,21 +65,6 @@ default_value=False, ) -OUTPUT_GRAPH_IRI_PARAMETER = PluginParameter( - param_type=GraphParameterType( - allow_only_autocompleted_values=False, - classes=[ - "https://vocab.eccenca.com/di/Dataset", - "http://rdfs.org/ns/void#Dataset", - "http://www.w3.org/2002/07/owl#Ontology", - ], - ), - name="output_graph_iri", - label="Output graph IRI", - description="""The IRI of the output graph for the inconsistency validation. ⚠️ Existing graphs - graphs will be overwritten.""", -) - def create_xml_catalog_file(dir_: str, graphs: dict) -> None: """Create XML catalog file""" diff --git a/poetry.lock b/poetry.lock index 2d5c841..4669b19 100644 --- a/poetry.lock +++ b/poetry.lock @@ -126,13 +126,13 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "cmem-cmempy" -version = "24.1.1" +version = "24.2.0" description = "API for eccenca Corporate Memory" optional = false python-versions = "<4.0,>=3.9" files = [ - {file = "cmem_cmempy-24.1.1-py3-none-any.whl", hash = "sha256:a335823a39518ba69ea07c3f047e567d6e80f75dd2e50f8b2afe73f7d0f056da"}, - {file = "cmem_cmempy-24.1.1.tar.gz", hash = "sha256:659ef5206dc7dd07a9cd8c9da98a8f5e6353cad397e5859dc418bc1684cb6eb6"}, + {file = "cmem_cmempy-24.2.0-py3-none-any.whl", hash = "sha256:0ceb9454ee88338ddb12d295ffbe5ecb86bd0d233dac23a72af865e8fa8c2202"}, + {file = "cmem_cmempy-24.2.0.tar.gz", hash = "sha256:3996f9d2dbe5d946525b70439858312208d83ceb87db5672979e9e8a84e4d19e"}, ] [package.dependencies] @@ -1064,18 +1064,18 @@ setuptools = "*" [[package]] name = "setuptools" -version = "72.1.0" +version = "72.2.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-72.1.0-py3-none-any.whl", hash = "sha256:5a03e1860cf56bb6ef48ce186b0e557fdba433237481a9a625176c2831be15d1"}, - {file = "setuptools-72.1.0.tar.gz", hash = "sha256:8d243eff56d095e5817f796ede6ae32941278f542e0f941867cc05ae52b162ec"}, + {file = "setuptools-72.2.0-py3-none-any.whl", hash = "sha256:f11dd94b7bae3a156a95ec151f24e4637fb4fa19c878e4d191bfb8b2d82728c4"}, + {file = "setuptools-72.2.0.tar.gz", hash = "sha256:80aacbf633704e9c8bfa1d99fa5dd4dc59573efcf9e4042c13d3bcef91ac2ef9"}, ] [package.extras] core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] [[package]] @@ -1167,4 +1167,4 @@ crypto-eth-addresses = ["eth-hash[pycryptodome] (>=0.7.0)"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "4df369a43e71446c9cbc562df56387e5f6607d84851c42188d3799874a8848bf" +content-hash = "aaa6d9426e01b3085332ea743e18779f30ff5fec6c0521b42203d4de17618458" diff --git a/pyproject.toml b/pyproject.toml index 9e6ef0c..42d9f3b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,6 @@ python = "^3.11" validators = "^0.33.0" pathvalidate = "^3.2.0" defusedxml = "^0.7.1" -urllib3 = "^2.2.2" inflection = "^0.5.1" [tool.poetry.dependencies.cmem-plugin-base] diff --git a/tests/test_reason.py b/tests/test_reason.py index e03d807..0ecab00 100644 --- a/tests/test_reason.py +++ b/tests/test_reason.py @@ -90,6 +90,7 @@ def test_validate(errors: str) -> str: result = ValidatePlugin( ontology_graph_iri=VALIDATE_ONTOLOGY_GRAPH_IRI, output_graph_iri=OUTPUT_GRAPH_IRI, + reasoner="elk", validate_profile=True, md_filename=MD_FILENAME, output_entities=True, From f6ee10645925157b55882ef9e936b4fb98a4b787 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Wed, 14 Aug 2024 18:04:30 +0100 Subject: [PATCH 31/32] remove SSL_VERIFY env variable setting --- cmem_plugin_reason/plugin_reason.py | 3 --- cmem_plugin_reason/plugin_validate.py | 4 ---- 2 files changed, 7 deletions(-) diff --git a/cmem_plugin_reason/plugin_reason.py b/cmem_plugin_reason/plugin_reason.py index 1144e72..ef97a62 100644 --- a/cmem_plugin_reason/plugin_reason.py +++ b/cmem_plugin_reason/plugin_reason.py @@ -1,7 +1,6 @@ """Reasoning workflow plugin module""" from datetime import UTC, datetime -from os import environ from pathlib import Path from tempfile import TemporaryDirectory from time import time @@ -36,8 +35,6 @@ validate_profiles, ) -environ["SSL_VERIFY"] = "false" - @Plugin( label="Reason", diff --git a/cmem_plugin_reason/plugin_validate.py b/cmem_plugin_reason/plugin_validate.py index b0d127b..5f3dff6 100644 --- a/cmem_plugin_reason/plugin_validate.py +++ b/cmem_plugin_reason/plugin_validate.py @@ -1,7 +1,6 @@ """Ontology consistency validation workflow plugin module""" from datetime import UTC, datetime -from os import environ from pathlib import Path from tempfile import TemporaryDirectory from time import time @@ -37,8 +36,6 @@ validate_profiles, ) -environ["SSL_VERIFY"] = "false" - @Plugin( label="Validate OWL consistency", @@ -279,6 +276,5 @@ def execute(self, inputs: None, context: ExecutionContext) -> Entities | None: operation_desc="ontologies validated.", ) ) - with TemporaryDirectory() as self.temp: return self._execute(context) From 5533ba16625f5c4acff260214c4dbb29b0b5fed6 Mon Sep 17 00:00:00 2001 From: muddymudskipper Date: Thu, 15 Aug 2024 12:59:59 +0100 Subject: [PATCH 32/32] specify output entity paths in Validate tests --- tests/test_reason.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/tests/test_reason.py b/tests/test_reason.py index 0ecab00..e6d48de 100644 --- a/tests/test_reason.py +++ b/tests/test_reason.py @@ -12,6 +12,7 @@ from cmem_plugin_reason.plugin_reason import ReasonPlugin from cmem_plugin_reason.plugin_validate import ValidatePlugin +from cmem_plugin_reason.utils import REASONERS from tests.utils import TestExecutionContext, needs_cmem from . import __path__ @@ -96,15 +97,22 @@ def test_validate(errors: str) -> str: output_entities=True, ).execute(None, context=TestExecutionContext(PROJECT_ID)) - val_errors = "" md_test = (Path(__path__[0]) / "test_validate.md").read_text() + paths = [p.path for p in result.schema.paths] # type: ignore[union-attr] + val_errors = "" - if next(iter(result.entities)).values[0][0] != md_test: # type: ignore[union-attr] + if next(iter(result.entities)).values[paths.index("markdown")][0] != md_test: # type: ignore[union-attr] val_errors += 'EntityPath "markdown" output error. ' - - if next(iter(result.entities)).values[2][0] != "Full,DL,EL,QL,RL": # type: ignore[union-attr] + if ( + next(iter(result.entities)).values[paths.index("ontology_graph_iri")][0] # type: ignore[union-attr] + != VALIDATE_ONTOLOGY_GRAPH_IRI + ): + val_errors += 'EntityPath "ontology_graph_iri" output error. ' + if ( + next(iter(result.entities)).values[paths.index("valid_profiles")][0] # type: ignore[union-attr] + != "Full,DL,EL,QL,RL" + ): val_errors += 'EntityPath "valid_profiles" output error. ' - if md_test != get_resource(PROJECT_ID, MD_FILENAME).decode(): val_errors += "Markdown file error. " @@ -118,8 +126,7 @@ def test_validate(errors: str) -> str: return errors errors_list: list[str] = [] - reasoners = ["elk", "emr", "hermit", "jfact", "structural", "whelk"] - for reasoner in reasoners: + for reasoner in REASONERS: errors_list = test_reasoner(reasoner, errors_list) errors = ""