From 252722434e8b89b1f62d9c29aacdcd1183f0e11a Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 25 Mar 2024 12:15:42 -0700 Subject: [PATCH 001/124] WIP: add export_as_graph flag to convert CLI command. --- schematic/schemas/commands.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index 35b7b96ee..211b97c31 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -6,6 +6,7 @@ import sys import time import re +import pickle from typing import get_args from schematic.schemas.data_model_parser import DataModelParser @@ -56,7 +57,13 @@ def schema(): # use as `schematic model ...` metavar="", help=query_dict(schema_commands, ("schema", "convert", "output_jsonld")), ) -def convert(schema, data_model_labels, output_jsonld): +@click.option( + "--export_as_graph", + "-eag", + is_flag=True, + help="Export the graph as a pickle file" +) +def convert(schema, data_model_labels, output_jsonld, export_as_graph): """ Running CLI to convert data model specification in CSV format to data model in JSON-LD format. @@ -105,6 +112,18 @@ def convert(schema, data_model_labels, output_jsonld): for w in war: logger.warning(w) + logger.info("Export graph to pickle if requested") + if export_as_graph: + if output_jsonld is None: + graph_file_no_ext = re.sub("[.](jsonld|csv)$", "", schema) + output_graph = graph_file_no_ext + ".pickle" + else: + graph_file_no_ext = re.sub("[.](jsonld|csv)$", "", output_jsonld) + output_graph = graph_file_no_ext + ".pickle" + with open(output_graph, "wb") as file: + pickle.dump(graph_data_model, file) + return output_graph + logger.info("Converting data model to JSON-LD") jsonld_data_model = convert_graph_to_jsonld(Graph=graph_data_model) From 70bfc1984a33f155fb197e241511be026e832854 Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 25 Mar 2024 12:34:05 -0700 Subject: [PATCH 002/124] Add convert CLI test for exporting graph as a pickle. --- tests/test_cli.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_cli.py b/tests/test_cli.py index 4631e9a9c..5825e6a1c 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -63,6 +63,12 @@ def test_schema_convert_cli(self, runner, helpers): assert expected_substr in result.output + graph_export = runner.invoke( + schema, ["convert", data_model_csv_path, "--export_as_graph"] + ) + + assert graph_export.exit_code == 0 + # get manifest by default # by default this should download the manifest as a CSV file @pytest.mark.google_credentials_needed From 5b41aa5042f2a6160247c8bddf1025ca81b5be05 Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 25 Mar 2024 14:25:20 -0700 Subject: [PATCH 003/124] Add export_as_graph to help.py and update the CLI click docs. --- schematic/help.py | 3 +++ schematic/schemas/commands.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/schematic/help.py b/schematic/help.py index 60f25a2c5..0c643c7ef 100644 --- a/schematic/help.py +++ b/schematic/help.py @@ -203,6 +203,9 @@ "output_jsonld": ( "Path to where the generated JSON-LD file needs to be outputted." ), + "export_as_graph": ( + "Export the graph as a pickle file." + ), "data_model_labels": DATA_MODEL_LABELS_HELP, } } diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index 211b97c31..b78901a4b 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -61,7 +61,7 @@ def schema(): # use as `schematic model ...` "--export_as_graph", "-eag", is_flag=True, - help="Export the graph as a pickle file" + help=query_dict(schema_commands, ("schema", "convert", "export_as_graph")), ) def convert(schema, data_model_labels, output_jsonld, export_as_graph): """ From 76a55670334d24e24bb312cad6143f753d3764a2 Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 25 Mar 2024 16:13:41 -0700 Subject: [PATCH 004/124] Change export_as_graph to output_format and specify graph, jsonld, or all. --- schematic/schemas/commands.py | 62 +++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index b78901a4b..b8f188de7 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -58,12 +58,13 @@ def schema(): # use as `schematic model ...` help=query_dict(schema_commands, ("schema", "convert", "output_jsonld")), ) @click.option( - "--export_as_graph", - "-eag", - is_flag=True, - help=query_dict(schema_commands, ("schema", "convert", "export_as_graph")), + "--output_type", + "-ot", + type=click.Choice(['jsonld', 'graph', 'all'], case_sensitive=False), + default="jsonld", + help=query_dict(schema_commands, ("schema", "convert", "output_type")), ) -def convert(schema, data_model_labels, output_jsonld, export_as_graph): +def convert(schema, data_model_labels, output_jsonld, output_type): """ Running CLI to convert data model specification in CSV format to data model in JSON-LD format. @@ -111,35 +112,40 @@ def convert(schema, data_model_labels, output_jsonld, export_as_graph): elif isinstance(war, list): for w in war: logger.warning(w) - - logger.info("Export graph to pickle if requested") - if export_as_graph: - if output_jsonld is None: - graph_file_no_ext = re.sub("[.](jsonld|csv)$", "", schema) - output_graph = graph_file_no_ext + ".pickle" - else: - graph_file_no_ext = re.sub("[.](jsonld|csv)$", "", output_jsonld) - output_graph = graph_file_no_ext + ".pickle" - with open(output_graph, "wb") as file: - pickle.dump(graph_data_model, file) + + if output_jsonld is None: + output_file_no_ext = re.sub("[.](jsonld|csv)$", "", schema) + else: + output_file_no_ext = re.sub("[.](jsonld|csv)$", "", output_jsonld) + + logger.info( + "By default, the JSON-LD output will be stored alongside the first " + f"input CSV or JSON-LD file. In this case, it will appear here: '{output_jsonld}'. " + "You can use the `--output_jsonld` argument to specify another file path." + ) + + if output_type in ["graph", "all"]: + logger.info("Export graph to pickle if requested") + output_graph = output_file_no_ext + ".pickle" + try: + with open(output_graph, "wb") as file: + pickle.dump(graph_data_model, file) + click.echo( + f"The graph was created and saved to '{output_graph}'." + ) + except: + click.echo( + f"The graph failed to save to '{output_graph}'. Please check your file path again." + ) + + if output_type == "graph": return output_graph logger.info("Converting data model to JSON-LD") jsonld_data_model = convert_graph_to_jsonld(Graph=graph_data_model) # output JSON-LD file alongside CSV file by default, get path. - if output_jsonld is None: - if not ".jsonld" in schema: - csv_no_ext = re.sub("[.]csv$", "", schema) - output_jsonld = csv_no_ext + ".jsonld" - else: - output_jsonld = schema - - logger.info( - "By default, the JSON-LD output will be stored alongside the first " - f"input CSV or JSON-LD file. In this case, it will appear here: '{output_jsonld}'. " - "You can use the `--output_jsonld` argument to specify another file path." - ) + output_jsonld = output_file_no_ext + ".jsonld" # saving updated schema.org schema try: From 670b5c7d8379cf511c1973f01fe84b73e076b6a5 Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 25 Mar 2024 16:14:09 -0700 Subject: [PATCH 005/124] Add tests for CLI convert output_type options. --- tests/test_cli.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 5825e6a1c..14635c2ac 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,6 +1,7 @@ import os import pytest +import pickle from click.testing import CliRunner @@ -46,6 +47,8 @@ def assert_expected_file(self, result, output_path): def test_schema_convert_cli(self, runner, helpers): data_model_csv_path = helpers.get_data_path("example.model.csv") + data_model_pickle_path = helpers.get_data_path("example.model.pickle") + data_model_jsonld_path = helpers.get_data_path("example.model.jsonld") output_path = helpers.get_data_path("example.model.jsonld") @@ -64,10 +67,32 @@ def test_schema_convert_cli(self, runner, helpers): assert expected_substr in result.output graph_export = runner.invoke( - schema, ["convert", data_model_csv_path, "--export_as_graph"] + schema, ["convert", data_model_csv_path, "--output_type", "graph"] ) + # Test that the command runs without error and the pickle file is read + # as miltidigraph class. assert graph_export.exit_code == 0 + with open(data_model_pickle_path, 'rb') as file: + graph_pickle = pickle.load(file) + assert type(graph_pickle).__name__.lower() == 'multidigraph' + os.remove(data_model_pickle_path) + + jsonld_export = runner.invoke( + schema, ["convert", data_model_csv_path, "--output_type", "jsonld"] + ) + + assert jsonld_export.exit_code == 0 + + all_export = runner.invoke( + schema, ["convert", data_model_csv_path, "--output_type", "all"] + ) + + assert all_export.exit_code == 0 + with open(data_model_pickle_path, 'rb') as file: + all_pickle = pickle.load(file) + assert type(all_pickle).__name__.lower() == 'multidigraph' + os.remove(data_model_pickle_path) # get manifest by default # by default this should download the manifest as a CSV file From a87d2fedad0575287d93eec4eb6113e8c736cc2a Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 25 Mar 2024 16:14:57 -0700 Subject: [PATCH 006/124] Change text of CLI convert output_type help. --- schematic/help.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/schematic/help.py b/schematic/help.py index 0c643c7ef..81083e48a 100644 --- a/schematic/help.py +++ b/schematic/help.py @@ -203,8 +203,8 @@ "output_jsonld": ( "Path to where the generated JSON-LD file needs to be outputted." ), - "export_as_graph": ( - "Export the graph as a pickle file." + "output_type": ( + "Output format to export the schema." ), "data_model_labels": DATA_MODEL_LABELS_HELP, } From 07dbd701bb32381d50ae48e98378da882e561a3f Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 25 Mar 2024 16:24:02 -0700 Subject: [PATCH 007/124] Test that jsonld is created correctly by convert CLI --- tests/test_cli.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test_cli.py b/tests/test_cli.py index 14635c2ac..45d7bc935 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -2,6 +2,7 @@ import pytest import pickle +import json from click.testing import CliRunner @@ -83,10 +84,18 @@ def test_schema_convert_cli(self, runner, helpers): ) assert jsonld_export.exit_code == 0 + with open(data_model_jsonld_path, 'r') as file: + json_jsonld = json.load(file) + assert '@context' in list(json_jsonld) + os.remove(data_model_jsonld_path) all_export = runner.invoke( schema, ["convert", data_model_csv_path, "--output_type", "all"] ) + with open(data_model_jsonld_path, 'r') as file: + all_jsonld = json.load(file) + assert '@context' in list(all_jsonld) + os.remove(data_model_jsonld_path) assert all_export.exit_code == 0 with open(data_model_pickle_path, 'rb') as file: From 421c59a01a48f830a34a2a17d9f11918e9aa0bfc Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 26 Mar 2024 08:38:55 -0700 Subject: [PATCH 008/124] Add type hints to convert, clean up formatting issues from sonarcloud scan. --- schematic/schemas/commands.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index b8f188de7..074c3c884 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -64,7 +64,7 @@ def schema(): # use as `schematic model ...` default="jsonld", help=query_dict(schema_commands, ("schema", "convert", "output_type")), ) -def convert(schema, data_model_labels, output_jsonld, output_type): +def convert(schema: str, data_model_labels:str, output_jsonld:str, output_type:str) -> str: """ Running CLI to convert data model specification in CSV format to data model in JSON-LD format. @@ -112,18 +112,18 @@ def convert(schema, data_model_labels, output_jsonld, output_type): elif isinstance(war, list): for w in war: logger.warning(w) - + if output_jsonld is None: output_file_no_ext = re.sub("[.](jsonld|csv)$", "", schema) else: output_file_no_ext = re.sub("[.](jsonld|csv)$", "", output_jsonld) - + logger.info( "By default, the JSON-LD output will be stored alongside the first " f"input CSV or JSON-LD file. In this case, it will appear here: '{output_jsonld}'. " "You can use the `--output_jsonld` argument to specify another file path." ) - + if output_type in ["graph", "all"]: logger.info("Export graph to pickle if requested") output_graph = output_file_no_ext + ".pickle" @@ -133,10 +133,11 @@ def convert(schema, data_model_labels, output_jsonld, output_type): click.echo( f"The graph was created and saved to '{output_graph}'." ) - except: + except SystemExit as e: click.echo( f"The graph failed to save to '{output_graph}'. Please check your file path again." ) + raise e if output_type == "graph": return output_graph From 2f5abf19e93fc6d597f3e840375bb9ffbe10aa88 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 26 Mar 2024 13:47:28 -0700 Subject: [PATCH 009/124] Add convert CLI test for not specifying --output_type --- tests/test_cli.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test_cli.py b/tests/test_cli.py index 45d7bc935..e730ecae1 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -103,6 +103,15 @@ def test_schema_convert_cli(self, runner, helpers): assert type(all_pickle).__name__.lower() == 'multidigraph' os.remove(data_model_pickle_path) + no_ot = runner.invoke( + schema, ["convert", data_model_csv_path] + ) + assert no_ot.exit_code == 0 + with open(data_model_jsonld_path, 'r') as file: + no_ot_json = json.load(file) + assert '@context' in list(no_ot_json) + os.remove(data_model_jsonld_path) + # get manifest by default # by default this should download the manifest as a CSV file @pytest.mark.google_credentials_needed From c6c5cb8015af30e16ae20ed49cf8e6fc4554fb82 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 3 Apr 2024 09:55:11 -0700 Subject: [PATCH 010/124] parameterize the convert CLI test. --- tests/test_cli.py | 78 ++++++++++++----------------------------------- 1 file changed, 20 insertions(+), 58 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index e730ecae1..247230c22 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -3,6 +3,7 @@ import pytest import pickle import json +import tempfile from click.testing import CliRunner @@ -26,6 +27,14 @@ def data_model_jsonld(helpers): class TestSchemaCli: + def setUp(self): + self.temp_dir = tempfile.mkdtemp() + self.temp_file = tempfile.NamedTemporaryFile(dir=self.temp_dir) + + def tearDown(self): + self.temp_file.close() + os.rmdir(self.temp_dir()) + def assert_expected_file(self, result, output_path): extension = os.path.splitext(output_path)[-1].lower() @@ -46,71 +55,24 @@ def assert_expected_file(self, result, output_path): except: pass - def test_schema_convert_cli(self, runner, helpers): - data_model_csv_path = helpers.get_data_path("example.model.csv") - data_model_pickle_path = helpers.get_data_path("example.model.pickle") - data_model_jsonld_path = helpers.get_data_path("example.model.jsonld") + @pytest.mark.parametrize("model, output, expected", [ + ("tests/data/example.model.csv", "tests/data/example.model.pickle", 0), + ("tests/data/example.model.csv", "tests/data/example.model.jsonld", 0) + ]) + def test_schema_convert_cli(self, runner, helpers, model, output, expected): + #data_model_path = helpers.get_data_path(model) + #data_model_pickle_path = helpers.get_data_path("example.model.pickle") + #data_model_jsonld_path = helpers.get_data_path("example.model.jsonld") - output_path = helpers.get_data_path("example.model.jsonld") + #output_path = helpers.get_data_path(output) label_type = 'class_label' result = runner.invoke( - schema, ["convert", data_model_csv_path, "--output_jsonld", output_path, "--data_model_labels", label_type] - ) - - assert result.exit_code == 0 - - expected_substr = ( - "The Data Model was created and saved to " f"'{output_path}' location." - ) - - assert expected_substr in result.output - - graph_export = runner.invoke( - schema, ["convert", data_model_csv_path, "--output_type", "graph"] - ) - - # Test that the command runs without error and the pickle file is read - # as miltidigraph class. - assert graph_export.exit_code == 0 - with open(data_model_pickle_path, 'rb') as file: - graph_pickle = pickle.load(file) - assert type(graph_pickle).__name__.lower() == 'multidigraph' - os.remove(data_model_pickle_path) - - jsonld_export = runner.invoke( - schema, ["convert", data_model_csv_path, "--output_type", "jsonld"] + schema, ["convert", model, "--output_jsonld", output, "--data_model_labels", label_type] ) - assert jsonld_export.exit_code == 0 - with open(data_model_jsonld_path, 'r') as file: - json_jsonld = json.load(file) - assert '@context' in list(json_jsonld) - os.remove(data_model_jsonld_path) - - all_export = runner.invoke( - schema, ["convert", data_model_csv_path, "--output_type", "all"] - ) - with open(data_model_jsonld_path, 'r') as file: - all_jsonld = json.load(file) - assert '@context' in list(all_jsonld) - os.remove(data_model_jsonld_path) - - assert all_export.exit_code == 0 - with open(data_model_pickle_path, 'rb') as file: - all_pickle = pickle.load(file) - assert type(all_pickle).__name__.lower() == 'multidigraph' - os.remove(data_model_pickle_path) - - no_ot = runner.invoke( - schema, ["convert", data_model_csv_path] - ) - assert no_ot.exit_code == 0 - with open(data_model_jsonld_path, 'r') as file: - no_ot_json = json.load(file) - assert '@context' in list(no_ot_json) - os.remove(data_model_jsonld_path) + assert result.exit_code == expected # get manifest by default # by default this should download the manifest as a CSV file From dd8b2cd4c641d356b50000abff7063b8eaf607ed Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 3 Apr 2024 09:56:30 -0700 Subject: [PATCH 011/124] remove unused test code for the convert CLI. --- tests/test_cli.py | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 247230c22..e3614ebc3 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -3,7 +3,6 @@ import pytest import pickle import json -import tempfile from click.testing import CliRunner @@ -27,14 +26,6 @@ def data_model_jsonld(helpers): class TestSchemaCli: - def setUp(self): - self.temp_dir = tempfile.mkdtemp() - self.temp_file = tempfile.NamedTemporaryFile(dir=self.temp_dir) - - def tearDown(self): - self.temp_file.close() - os.rmdir(self.temp_dir()) - def assert_expected_file(self, result, output_path): extension = os.path.splitext(output_path)[-1].lower() @@ -60,12 +51,6 @@ def assert_expected_file(self, result, output_path): ("tests/data/example.model.csv", "tests/data/example.model.jsonld", 0) ]) def test_schema_convert_cli(self, runner, helpers, model, output, expected): - #data_model_path = helpers.get_data_path(model) - #data_model_pickle_path = helpers.get_data_path("example.model.pickle") - #data_model_jsonld_path = helpers.get_data_path("example.model.jsonld") - - #output_path = helpers.get_data_path(output) - label_type = 'class_label' result = runner.invoke( From 6ec81db773be6fb203d249e331cea07a854c86b4 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 3 Apr 2024 10:00:52 -0700 Subject: [PATCH 012/124] run black on the updated files. --- schematic/help.py | 4 +--- schematic/schemas/commands.py | 10 +++++----- tests/test_cli.py | 23 +++++++++++++++++------ 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/schematic/help.py b/schematic/help.py index 81083e48a..cdd7de4c4 100644 --- a/schematic/help.py +++ b/schematic/help.py @@ -203,9 +203,7 @@ "output_jsonld": ( "Path to where the generated JSON-LD file needs to be outputted." ), - "output_type": ( - "Output format to export the schema." - ), + "output_type": ("Output format to export the schema."), "data_model_labels": DATA_MODEL_LABELS_HELP, } } diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index 074c3c884..6653f6089 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -60,11 +60,13 @@ def schema(): # use as `schematic model ...` @click.option( "--output_type", "-ot", - type=click.Choice(['jsonld', 'graph', 'all'], case_sensitive=False), + type=click.Choice(["jsonld", "graph", "all"], case_sensitive=False), default="jsonld", help=query_dict(schema_commands, ("schema", "convert", "output_type")), ) -def convert(schema: str, data_model_labels:str, output_jsonld:str, output_type:str) -> str: +def convert( + schema: str, data_model_labels: str, output_jsonld: str, output_type: str +) -> str: """ Running CLI to convert data model specification in CSV format to data model in JSON-LD format. @@ -130,9 +132,7 @@ def convert(schema: str, data_model_labels:str, output_jsonld:str, output_type:s try: with open(output_graph, "wb") as file: pickle.dump(graph_data_model, file) - click.echo( - f"The graph was created and saved to '{output_graph}'." - ) + click.echo(f"The graph was created and saved to '{output_graph}'.") except SystemExit as e: click.echo( f"The graph failed to save to '{output_graph}'. Please check your file path again." diff --git a/tests/test_cli.py b/tests/test_cli.py index e3614ebc3..2db0a4021 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -46,15 +46,26 @@ def assert_expected_file(self, result, output_path): except: pass - @pytest.mark.parametrize("model, output, expected", [ - ("tests/data/example.model.csv", "tests/data/example.model.pickle", 0), - ("tests/data/example.model.csv", "tests/data/example.model.jsonld", 0) - ]) + @pytest.mark.parametrize( + "model, output, expected", + [ + ("tests/data/example.model.csv", "tests/data/example.model.pickle", 0), + ("tests/data/example.model.csv", "tests/data/example.model.jsonld", 0), + ], + ) def test_schema_convert_cli(self, runner, helpers, model, output, expected): - label_type = 'class_label' + label_type = "class_label" result = runner.invoke( - schema, ["convert", model, "--output_jsonld", output, "--data_model_labels", label_type] + schema, + [ + "convert", + model, + "--output_jsonld", + output, + "--data_model_labels", + label_type, + ], ) assert result.exit_code == expected From bbe6c98af61f0daa831158b9fe46ebf9d5d47332 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 3 Apr 2024 15:30:40 -0700 Subject: [PATCH 013/124] Use logger.info and logger.error instead of click.echo. --- schematic/schemas/commands.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index 6653f6089..2bbd3aac8 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -127,14 +127,14 @@ def convert( ) if output_type in ["graph", "all"]: - logger.info("Export graph to pickle if requested") + logger.info("Export graph to pickle.") output_graph = output_file_no_ext + ".pickle" try: with open(output_graph, "wb") as file: pickle.dump(graph_data_model, file) - click.echo(f"The graph was created and saved to '{output_graph}'.") + logger.info(f"The graph was created and saved to '{output_graph}'.") except SystemExit as e: - click.echo( + logger.error( f"The graph failed to save to '{output_graph}'. Please check your file path again." ) raise e @@ -151,11 +151,11 @@ def convert( # saving updated schema.org schema try: export_schema(jsonld_data_model, output_jsonld) - click.echo( + logger.info( f"The Data Model was created and saved to '{output_jsonld}' location." ) except: - click.echo( + logger.error( f"The Data Model could not be created by using '{output_jsonld}' location. Please check your file path again" ) @@ -164,4 +164,4 @@ def convert( # get the execution time elapsed_time = time.strftime("%M:%S", time.gmtime(et - st)) - click.echo(f"Execution time: {elapsed_time} (M:S)") + logger.info(f"Execution time: {elapsed_time} (M:S)") From b99d9ebf06ec1c3e50234bef033eb496b9e334d0 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 9 Apr 2024 15:45:19 -0700 Subject: [PATCH 014/124] Trim pickle from end of filename, in addition to csv and jsonld. --- schematic/schemas/commands.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index 2bbd3aac8..9f511bb1a 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -116,9 +116,9 @@ def convert( logger.warning(w) if output_jsonld is None: - output_file_no_ext = re.sub("[.](jsonld|csv)$", "", schema) + output_file_no_ext = re.sub("[.](jsonld|csv|pickle)$", "", schema) else: - output_file_no_ext = re.sub("[.](jsonld|csv)$", "", output_jsonld) + output_file_no_ext = re.sub("[.](jsonld|csv|pickle)$", "", output_jsonld) logger.info( "By default, the JSON-LD output will be stored alongside the first " From 11891079dee6069e2033b4aaed45e44bb0560fef Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 9 Apr 2024 15:50:12 -0700 Subject: [PATCH 015/124] add output_path alias for output_jsonld --- schematic/schemas/commands.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index 9f511bb1a..65236910b 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -57,6 +57,10 @@ def schema(): # use as `schematic model ...` metavar="", help=query_dict(schema_commands, ("schema", "convert", "output_jsonld")), ) +@click.option( + "--output_path", + help="Alias for --output_jsonld" +) @click.option( "--output_type", "-ot", @@ -65,7 +69,7 @@ def schema(): # use as `schematic model ...` help=query_dict(schema_commands, ("schema", "convert", "output_type")), ) def convert( - schema: str, data_model_labels: str, output_jsonld: str, output_type: str + schema: str, data_model_labels: str, output_jsonld: str, output_type: str, output_path: str ) -> str: """ Running CLI to convert data model specification in CSV format to @@ -115,6 +119,9 @@ def convert( for w in war: logger.warning(w) + if output_path: + output_jsonld = output_path + if output_jsonld is None: output_file_no_ext = re.sub("[.](jsonld|csv|pickle)$", "", schema) else: From 86f7af8888bbfdd079f76e5172c6d4a7550005ff Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 10 Apr 2024 09:58:59 -0700 Subject: [PATCH 016/124] Add combination of arguments to convert CLI tests --- tests/test_cli.py | 64 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 2db0a4021..a5eb395f4 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -50,12 +50,68 @@ def assert_expected_file(self, result, output_path): "model, output, expected", [ ("tests/data/example.model.csv", "tests/data/example.model.pickle", 0), - ("tests/data/example.model.csv", "tests/data/example.model.jsonld", 0), - ], + ("tests/data/example.model.csv", "tests/data/example.model.jsonld", 0) + ] ) - def test_schema_convert_cli(self, runner, helpers, model, output, expected): + @pytest.mark.parametrize( + "output_type", + [ + "jsonld", + "graph", + "all" + ] + ) + def test_schema_convert_cli(self, runner, model, output, output_type, expected): label_type = "class_label" + resultOne = runner.invoke( + schema, + [ + "convert", + model + ] + ) + + assert resultOne.exit_code == expected + + resultTwo = runner.invoke( + schema, + [ + "convert", + model, + "--output_path", + output + ] + ) + + assert resultTwo.exit_code == expected + + resultThree = runner.invoke( + schema, + [ + "convert", + model, + "--output_type", + output_type + ] + ) + + assert resultThree.exit_code == expected + + resultFour = runner.invoke( + schema, + [ + "convert", + model, + "--output_type", + output_type, + "--output_jsonld", + output + ] + ) + + assert resultFour.exit_code == expected + result = runner.invoke( schema, [ @@ -65,7 +121,7 @@ def test_schema_convert_cli(self, runner, helpers, model, output, expected): output, "--data_model_labels", label_type, - ], + ] ) assert result.exit_code == expected From d3c37696d04f8725ebebe83aca522ce5eae36964 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 10 Apr 2024 10:15:33 -0700 Subject: [PATCH 017/124] add export_graph to schema_utils.py to dump a pickle file --- schematic/utils/schema_utils.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/schematic/utils/schema_utils.py b/schematic/utils/schema_utils.py index 6a3a2c4e0..712059d39 100644 --- a/schematic/utils/schema_utils.py +++ b/schematic/utils/schema_utils.py @@ -6,6 +6,7 @@ import logging import string from typing import Literal, Union, Optional +import pickle import inflection @@ -480,3 +481,14 @@ def strip_context(context_value: str) -> tuple[str, str]: elif "@" in context_value: context, value = context_value.split("@") return context, value + +def export_graph(schema, file_path: str) -> None: + try: + with open(file_path, "wb") as f: + pickle.dump(schema, f) + logger.info(f"The graph was created and saved to '{file_path}'.") + except SystemExit as e: + logger.error( + f"The graph failed to save to '{file_path}'. Please check your file path again." + ) + raise e \ No newline at end of file From 215cc867b0b6aaf46b258035fd2c691c8ce52eae Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 10 Apr 2024 10:16:10 -0700 Subject: [PATCH 018/124] use export_graph util to save pickle file instead of handling that logic in the CLI function --- schematic/schemas/commands.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index 65236910b..488d12888 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -6,7 +6,6 @@ import sys import time import re -import pickle from typing import get_args from schematic.schemas.data_model_parser import DataModelParser @@ -16,7 +15,7 @@ from schematic.utils.schema_utils import DisplayLabelType from schematic.utils.cli_utils import query_dict -from schematic.utils.schema_utils import export_schema +from schematic.utils.schema_utils import export_schema, export_graph from schematic.help import schema_commands logger = logging.getLogger("schematic") @@ -137,13 +136,8 @@ def convert( logger.info("Export graph to pickle.") output_graph = output_file_no_ext + ".pickle" try: - with open(output_graph, "wb") as file: - pickle.dump(graph_data_model, file) - logger.info(f"The graph was created and saved to '{output_graph}'.") + export_graph(graph_data_model, output_graph) except SystemExit as e: - logger.error( - f"The graph failed to save to '{output_graph}'. Please check your file path again." - ) raise e if output_type == "graph": From 242c8850662ef2aefa799dee2d18cf6eceae5197 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 10 Apr 2024 14:36:18 -0700 Subject: [PATCH 019/124] add docstrings to graph_export --- schematic/utils/schema_utils.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/schematic/utils/schema_utils.py b/schematic/utils/schema_utils.py index 712059d39..a37ebe283 100644 --- a/schematic/utils/schema_utils.py +++ b/schematic/utils/schema_utils.py @@ -482,7 +482,12 @@ def strip_context(context_value: str) -> tuple[str, str]: context, value = context_value.split("@") return context, value -def export_graph(schema, file_path: str) -> None: +def export_graph(schema: dict, file_path: str) -> None: + """Write object to a pickle file. + Args: + schema, dict: A data model graph to export + file_path, str: File to create + """ try: with open(file_path, "wb") as f: pickle.dump(schema, f) From a1cfcce1178c1745167d26db1c19469d099ca4bf Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 10 Apr 2024 14:36:57 -0700 Subject: [PATCH 020/124] Update tests to run different combinations of output_jsonld and output_type --- tests/test_cli.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index a5eb395f4..9f46754ee 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -47,11 +47,12 @@ def assert_expected_file(self, result, output_path): pass @pytest.mark.parametrize( - "model, output, expected", + "output_path", [ - ("tests/data/example.model.csv", "tests/data/example.model.pickle", 0), - ("tests/data/example.model.csv", "tests/data/example.model.jsonld", 0) - ] + "tests/data/example.model.pickle", + "tests/data/example.model.jsonld" + ], + ids=["output_path_pickle", "output_path_jsonld"] ) @pytest.mark.parametrize( "output_type", @@ -59,10 +60,13 @@ def assert_expected_file(self, result, output_path): "jsonld", "graph", "all" - ] + ], + ids=["output_type_jsonld", "output_type_graph", "output_type_all"] ) - def test_schema_convert_cli(self, runner, model, output, output_type, expected): + def test_schema_convert_cli(self, runner, output_path, output_type): + model = "tests/data/example.model.csv" label_type = "class_label" + expected = 0 resultOne = runner.invoke( schema, @@ -80,7 +84,7 @@ def test_schema_convert_cli(self, runner, model, output, output_type, expected): "convert", model, "--output_path", - output + output_path ] ) @@ -106,7 +110,7 @@ def test_schema_convert_cli(self, runner, model, output, output_type, expected): "--output_type", output_type, "--output_jsonld", - output + output_path ] ) @@ -118,7 +122,7 @@ def test_schema_convert_cli(self, runner, model, output, output_type, expected): "convert", model, "--output_jsonld", - output, + output_path, "--data_model_labels", label_type, ] From 1c67b4aab074c760f397c50d50d63097417f11d1 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 11 Apr 2024 12:47:28 -0700 Subject: [PATCH 021/124] Add data_model_graph_pickle to generator --- schematic/manifest/generator.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/schematic/manifest/generator.py b/schematic/manifest/generator.py index 5aced191e..5413389b5 100644 --- a/schematic/manifest/generator.py +++ b/schematic/manifest/generator.py @@ -1633,6 +1633,7 @@ def create_manifests( title: Optional[str] = None, strict: Optional[bool] = True, use_annotations: Optional[bool] = False, + graph_data_model: Optional[nx.MultiDiGraph] = None, ) -> Union[List[str], List[pd.DataFrame]]: """Create multiple manifests @@ -1668,16 +1669,17 @@ def create_manifests( "Please check your submission and try again." ) - data_model_parser = DataModelParser(path_to_data_model=path_to_data_model) + if not graph_data_model: + data_model_parser = DataModelParser(path_to_data_model=path_to_data_model) - # Parse Model - parsed_data_model = data_model_parser.parse_model() + # Parse Model + parsed_data_model = data_model_parser.parse_model() - # Instantiate DataModelGraph - data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) + # Instantiate DataModelGraph + data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) - # Generate graph - graph_data_model = data_model_grapher.graph + # Generate graph + graph_data_model = data_model_grapher.graph # Gather all returned result urls all_results = [] From a986b393af4a4cf61d0bd412967b722d88647fcb Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 11 Apr 2024 12:47:48 -0700 Subject: [PATCH 022/124] Add ata_model_graph_pickle to metadata.py --- schematic/models/metadata.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/schematic/models/metadata.py b/schematic/models/metadata.py index b8c0e325a..34a083e6b 100644 --- a/schematic/models/metadata.py +++ b/schematic/models/metadata.py @@ -3,6 +3,7 @@ import networkx as nx from os.path import exists from jsonschema import ValidationError +import pickle # allows specifying explicit variable types from typing import Any, Dict, Optional, Text, List @@ -39,6 +40,7 @@ def __init__( inputMModelLocation: str, inputMModelLocationType: str, data_model_labels: str, + data_model_graph_pickle: Optional[str] = None ) -> None: """Instantiates a MetadataModel object. @@ -52,20 +54,25 @@ def __init__( logger.debug( f"Initializing DataModelGraphExplorer object from {inputMModelLocation} schema." ) - + self.inputMModelLocation = inputMModelLocation - data_model_parser = DataModelParser(path_to_data_model=self.inputMModelLocation) - # Parse Model - parsed_data_model = data_model_parser.parse_model() + # Use graph, if provided. Otherwise parse data model for graph. + if data_model_graph_pickle: + with open(data_model_graph_pickle, 'rb') as f: + self.graph_data_model = pickle.load(f) + else: + data_model_parser = DataModelParser(path_to_data_model=self.inputMModelLocation) + # Parse Model + parsed_data_model = data_model_parser.parse_model() - # Instantiate DataModelGraph - data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) + # Instantiate DataModelGraph + data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) - # Generate graph - self.graph_data_model = data_model_grapher.graph + # Generate graph + self.graph_data_model = data_model_grapher.graph - self.dmge = DataModelGraphExplorer(self.graph_data_model) + self.dmge = DataModelGraphExplorer(self.graph_data_model) # check if the type of MModel file is "local" # currently, the application only supports reading from local JSON-LD files From 0390b69d136d5a8e3c275faa1e5a09ec9512475a Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 11 Apr 2024 12:48:26 -0700 Subject: [PATCH 023/124] Add data_model_graph to attributes_explorer --- schematic/visualization/attributes_explorer.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/schematic/visualization/attributes_explorer.py b/schematic/visualization/attributes_explorer.py index 9691932e7..c60c10a6e 100644 --- a/schematic/visualization/attributes_explorer.py +++ b/schematic/visualization/attributes_explorer.py @@ -5,6 +5,7 @@ from typing import Optional, no_type_check import numpy as np import pandas as pd +import networkx as nx from schematic.schemas.data_model_parser import DataModelParser from schematic.schemas.data_model_graph import DataModelGraph, DataModelGraphExplorer @@ -26,6 +27,7 @@ def __init__( data_model_grapher: Optional[DataModelGraph] = None, data_model_graph_explorer: Optional[DataModelGraphExplorer] = None, parsed_data_model: Optional[dict] = None, + graph_data_model: Optional[nx.MultiDiGraph] = None, ) -> None: self.path_to_jsonld = path_to_jsonld From 37bbf744473b10a5250fbc48ba8d74fae114f20f Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 11 Apr 2024 12:48:54 -0700 Subject: [PATCH 024/124] Add data_model_graph_pickle to tangled_tree --- schematic/visualization/tangled_tree.py | 35 ++++++++++++++----------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/schematic/visualization/tangled_tree.py b/schematic/visualization/tangled_tree.py index 59ba62139..a289bf334 100644 --- a/schematic/visualization/tangled_tree.py +++ b/schematic/visualization/tangled_tree.py @@ -51,27 +51,31 @@ def __init__( path_to_json_ld: str, figure_type: FigureType, data_model_labels: DisplayLabelType, + graph_data_model: Optional[nx.MultiDiGraph] = None, ) -> None: - # Load jsonld - self.path_to_json_ld = path_to_json_ld - self.json_data_model = load_json(self.path_to_json_ld) + if graph_data_model: + self.graph_data_model = graph_data_model + else: + # Load jsonld + self.path_to_json_ld = path_to_json_ld + self.json_data_model = load_json(self.path_to_json_ld) - # Parse schema name - self.schema_name = path.basename(self.path_to_json_ld).split(".model.jsonld")[0] + # Parse schema name + self.schema_name = path.basename(self.path_to_json_ld).split(".model.jsonld")[0] - # Instantiate Data Model Parser - data_model_parser = DataModelParser( - path_to_data_model=self.path_to_json_ld, - ) + # Instantiate Data Model Parser + data_model_parser = DataModelParser( + path_to_data_model=self.path_to_json_ld, + ) - # Parse Model - parsed_data_model = data_model_parser.parse_model() + # Parse Model + parsed_data_model = data_model_parser.parse_model() - # Instantiate DataModelGraph - data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) + # Instantiate DataModelGraph + data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) - # Generate graph - self.graph_data_model = data_model_grapher.graph + # Generate graph + self.graph_data_model = data_model_grapher.graph # Instantiate Data Model Graph Explorer self.dmge = DataModelGraphExplorer(self.graph_data_model) @@ -91,6 +95,7 @@ def __init__( data_model_grapher=data_model_grapher, data_model_graph_explorer=self.dmge, parsed_data_model=parsed_data_model, + graph_data_model=graph_data_model, ) # Create output paths. From 441b865bdbee62fbf5fe1dff91b1cfcd0938ef40 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 18 Apr 2024 14:57:32 -0700 Subject: [PATCH 025/124] Add convert CLI test case where output_jsonld is pickle and output_path is pickle. Also test both parameters are empty. --- tests/test_cli.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/test_cli.py b/tests/test_cli.py index 9f46754ee..fdefa52f2 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -130,6 +130,39 @@ def test_schema_convert_cli(self, runner, output_path, output_type): assert result.exit_code == expected + def test_schema_convert_cli(self, runner): + model = "tests/data/example.model.csv" + label_type = "class_label" + expected = 0 + + result = runner.invoke( + schema, + [ + "convert", + model, + "--output_jsonld", + "tests/data/example.model.pickle", + "--output_path", + "tests/data/example.model.pickle" + ] + ) + + assert result.exit_code == expected + + resultTwo = runner.invoke( + schema, + [ + "convert", + model, + "--output_jsonld", + "", + "--output_path", + "" + ] + ) + + assert resultTwo.exit_code == expected + # get manifest by default # by default this should download the manifest as a CSV file @pytest.mark.google_credentials_needed From fe4fffb4fe0648d1b944533f03d8480a42ea9337 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 18 Apr 2024 15:24:49 -0700 Subject: [PATCH 026/124] move tests into one function --- tests/test_cli.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index fdefa52f2..2570ade0c 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -130,12 +130,7 @@ def test_schema_convert_cli(self, runner, output_path, output_type): assert result.exit_code == expected - def test_schema_convert_cli(self, runner): - model = "tests/data/example.model.csv" - label_type = "class_label" - expected = 0 - - result = runner.invoke( + resultFive = runner.invoke( schema, [ "convert", @@ -147,9 +142,9 @@ def test_schema_convert_cli(self, runner): ] ) - assert result.exit_code == expected + assert resultFive.exit_code == expected - resultTwo = runner.invoke( + resultSix = runner.invoke( schema, [ "convert", @@ -161,7 +156,7 @@ def test_schema_convert_cli(self, runner): ] ) - assert resultTwo.exit_code == expected + assert resultSix.exit_code == expected # get manifest by default # by default this should download the manifest as a CSV file From f20f88b9e90ed4742e8c9808cafa881a9e97bf49 Mon Sep 17 00:00:00 2001 From: afwillia Date: Fri, 19 Apr 2024 11:33:15 -0700 Subject: [PATCH 027/124] Run black on commands.py and schema_utils.py --- schematic/schemas/commands.py | 11 ++++++----- schematic/utils/schema_utils.py | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index acd903e1d..8ac07c241 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -59,10 +59,7 @@ def schema(): # use as `schematic model ...` metavar="", help=query_dict(schema_commands, ("schema", "convert", "output_jsonld")), ) -@click.option( - "--output_path", - help="Alias for --output_jsonld" -) +@click.option("--output_path", help="Alias for --output_jsonld") @click.option( "--output_type", "-ot", @@ -71,7 +68,11 @@ def schema(): # use as `schematic model ...` help=query_dict(schema_commands, ("schema", "convert", "output_type")), ) def convert( - schema: str, data_model_labels: str, output_jsonld: str, output_type: str, output_path: str + schema: str, + data_model_labels: str, + output_jsonld: str, + output_type: str, + output_path: str, ) -> str: """ Running CLI to convert data model specification in CSV format to diff --git a/schematic/utils/schema_utils.py b/schematic/utils/schema_utils.py index f6cffc194..ba665b8e7 100644 --- a/schematic/utils/schema_utils.py +++ b/schematic/utils/schema_utils.py @@ -484,6 +484,7 @@ def strip_context(context_value: str) -> tuple[str, str]: context, value = context_value.split("@") return context, value + def export_graph(schema: dict, file_path: str) -> None: """Write object to a pickle file. Args: @@ -498,4 +499,4 @@ def export_graph(schema: dict, file_path: str) -> None: logger.error( f"The graph failed to save to '{file_path}'. Please check your file path again." ) - raise e \ No newline at end of file + raise e From d56c96571704086e66fa27a930c3c23c9cdde235 Mon Sep 17 00:00:00 2001 From: afwillia Date: Fri, 19 Apr 2024 11:40:55 -0700 Subject: [PATCH 028/124] fix single-letter variable names for pylint error --- schematic/schemas/commands.py | 4 ++-- schematic/utils/schema_utils.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index 8ac07c241..b1a257bed 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -145,8 +145,8 @@ def convert( output_graph = output_file_no_ext + ".pickle" try: export_graph(graph_data_model, output_graph) - except SystemExit as e: - raise e + except SystemExit as error: + raise error if output_type == "graph": return output_graph diff --git a/schematic/utils/schema_utils.py b/schematic/utils/schema_utils.py index ba665b8e7..154c23dd2 100644 --- a/schematic/utils/schema_utils.py +++ b/schematic/utils/schema_utils.py @@ -492,11 +492,11 @@ def export_graph(schema: dict, file_path: str) -> None: file_path, str: File to create """ try: - with open(file_path, "wb") as f: - pickle.dump(schema, f) + with open(file_path, "wb") as file: + pickle.dump(schema, file) logger.info(f"The graph was created and saved to '{file_path}'.") - except SystemExit as e: + except SystemExit as error: logger.error( f"The graph failed to save to '{file_path}'. Please check your file path again." ) - raise e + raise error From b5dd8e4c69fb40014dd9ba70cf7c6c4ed710b4c8 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 7 May 2024 17:09:12 -0700 Subject: [PATCH 029/124] Add data_model_graph argument to ManifestGenerator.create_manifests --- schematic/manifest/generator.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/schematic/manifest/generator.py b/schematic/manifest/generator.py index 5413389b5..07dcdf95c 100644 --- a/schematic/manifest/generator.py +++ b/schematic/manifest/generator.py @@ -11,6 +11,7 @@ import pygsheets as ps from tempfile import NamedTemporaryFile from typing import Any, Dict, List, Optional, Tuple, Union, BinaryIO, Literal +import pickle from schematic.schemas.data_model_graph import DataModelGraph, DataModelGraphExplorer from schematic.schemas.data_model_parser import DataModelParser @@ -1634,11 +1635,13 @@ def create_manifests( strict: Optional[bool] = True, use_annotations: Optional[bool] = False, graph_data_model: Optional[nx.MultiDiGraph] = None, + data_model_graph_pickle: str = None ) -> Union[List[str], List[pd.DataFrame]]: """Create multiple manifests Args: path_to_data_model (str): str path to data model + data_model_graph_pickle (str): A data model graph as csv or pickle data_types (list): a list of data types access_token (str, optional): synapse access token. Required when getting an existing manifest. Defaults to None. dataset_ids (list, optional): a list of dataset ids when generating an existing manifest. Defaults to None. @@ -1670,16 +1673,19 @@ def create_manifests( ) if not graph_data_model: - data_model_parser = DataModelParser(path_to_data_model=path_to_data_model) + if data_model_graph_pickle: + graph_data_model = pickle.Unpickler(data_model_graph_pickle) + else: + data_model_parser = DataModelParser(path_to_data_model=path_to_data_model) - # Parse Model - parsed_data_model = data_model_parser.parse_model() + # Parse Model + parsed_data_model = data_model_parser.parse_model() - # Instantiate DataModelGraph - data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) + # Instantiate DataModelGraph + data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) - # Generate graph - graph_data_model = data_model_grapher.graph + # Generate graph + graph_data_model = data_model_grapher.graph # Gather all returned result urls all_results = [] From c8da9000fd4648e0f74e8f6602d466879db34a37 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 8 May 2024 06:56:46 -0700 Subject: [PATCH 030/124] use pickle.load to read pickle file --- schematic/manifest/generator.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/schematic/manifest/generator.py b/schematic/manifest/generator.py index 07dcdf95c..8adc51d21 100644 --- a/schematic/manifest/generator.py +++ b/schematic/manifest/generator.py @@ -1674,7 +1674,8 @@ def create_manifests( if not graph_data_model: if data_model_graph_pickle: - graph_data_model = pickle.Unpickler(data_model_graph_pickle) + with open(data_model_graph_pickle, 'rb') as f: + graph_data_model = pickle.load(f) else: data_model_parser = DataModelParser(path_to_data_model=path_to_data_model) From 601b5d07b8ddce18ba67d9332d57d110352286cc Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 8 May 2024 08:00:43 -0700 Subject: [PATCH 031/124] Add data model graph pickle to attributes_explorer --- schematic/visualization/attributes_explorer.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/schematic/visualization/attributes_explorer.py b/schematic/visualization/attributes_explorer.py index c60c10a6e..28e8bdde4 100644 --- a/schematic/visualization/attributes_explorer.py +++ b/schematic/visualization/attributes_explorer.py @@ -6,6 +6,7 @@ import numpy as np import pandas as pd import networkx as nx +import pickle from schematic.schemas.data_model_parser import DataModelParser from schematic.schemas.data_model_graph import DataModelGraph, DataModelGraphExplorer @@ -28,6 +29,7 @@ def __init__( data_model_graph_explorer: Optional[DataModelGraphExplorer] = None, parsed_data_model: Optional[dict] = None, graph_data_model: Optional[nx.MultiDiGraph] = None, + data_model_graph_pickle: Optional[str] = None, ) -> None: self.path_to_jsonld = path_to_jsonld @@ -40,6 +42,10 @@ def __init__( ) parsed_data_model = data_model_parser.parse_model() + if data_model_graph_pickle: + with open(data_model_graph_pickle, 'rb') as f: + parsed_data_model = pickle.load(f) + # Instantiate DataModelGraph if not data_model_grapher: data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) From c6d01def4a7c2400660e50c9ab4d6d1aebc8638a Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 8 May 2024 08:00:59 -0700 Subject: [PATCH 032/124] Add data model graph pickle to tangled_tree --- schematic/visualization/tangled_tree.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/schematic/visualization/tangled_tree.py b/schematic/visualization/tangled_tree.py index a289bf334..2b4a48b2b 100644 --- a/schematic/visualization/tangled_tree.py +++ b/schematic/visualization/tangled_tree.py @@ -10,6 +10,7 @@ from os import path from typing import Optional, Literal, TypedDict, Union from typing_extensions import assert_never +import pickle import networkx as nx # type: ignore from networkx.classes.reportviews import NodeView, EdgeDataView # type: ignore @@ -52,6 +53,7 @@ def __init__( figure_type: FigureType, data_model_labels: DisplayLabelType, graph_data_model: Optional[nx.MultiDiGraph] = None, + data_model_graph_pickle: Optional[str] = None, ) -> None: if graph_data_model: self.graph_data_model = graph_data_model @@ -64,18 +66,23 @@ def __init__( self.schema_name = path.basename(self.path_to_json_ld).split(".model.jsonld")[0] # Instantiate Data Model Parser - data_model_parser = DataModelParser( - path_to_data_model=self.path_to_json_ld, - ) + if not data_model_graph_pickle: + data_model_parser = DataModelParser( + path_to_data_model=self.path_to_json_ld, + ) - # Parse Model - parsed_data_model = data_model_parser.parse_model() + # Parse Model + parsed_data_model = data_model_parser.parse_model() - # Instantiate DataModelGraph - data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) + # Instantiate DataModelGraph + data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) - # Generate graph - self.graph_data_model = data_model_grapher.graph + # Generate graph + self.graph_data_model = data_model_grapher.graph + + else: + with open(data_model_graph_pickle, 'rb') as f: + self.graph_data_model = pickle.load(f) # Instantiate Data Model Graph Explorer self.dmge = DataModelGraphExplorer(self.graph_data_model) From 1f57cf1d876253728a259b304bcf77913f0dac23 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 5 Jun 2024 09:52:11 -0700 Subject: [PATCH 033/124] return 0 to resolve a pylint error. --- schematic/schemas/commands.py | 1 + 1 file changed, 1 insertion(+) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index b1a257bed..b05922977 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -175,3 +175,4 @@ def convert( # get the execution time elapsed_time = time.strftime("%M:%S", time.gmtime(end_time - start_time)) click.echo(f"Execution time: {elapsed_time} (M:S)") + return 0 From d89dc10d12207091f913bf022c41052f26e72770 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 5 Jun 2024 10:02:18 -0700 Subject: [PATCH 034/124] remove extra function def from merge --- schematic/schemas/commands.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index af1636937..d8b998be5 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -74,9 +74,6 @@ def convert( output_type: Optional[str], output_path: Optional[str], ) -> str: -def convert( - schema: Any, data_model_labels: DisplayLabelType, output_jsonld: Optional[str] -) -> None: """ Running CLI to convert data model specification in CSV format to data model in JSON-LD format. From c9786dcfaef3bb7bff2abdd7946bc5d4186fcfeb Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 5 Jun 2024 10:02:39 -0700 Subject: [PATCH 035/124] run black on utils/schema_utils.py --- schematic/utils/schema_utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/schematic/utils/schema_utils.py b/schematic/utils/schema_utils.py index a6c84ce19..3c9af0ef8 100644 --- a/schematic/utils/schema_utils.py +++ b/schematic/utils/schema_utils.py @@ -485,6 +485,7 @@ def strip_context(context_value: str) -> tuple[str, str]: context, value = context_value.split("@") return context, value + def get_json_schema_log_file_path(data_model_path: str, source_node: str) -> str: """Get json schema log file name from the data_mdoel_path Args: @@ -501,6 +502,7 @@ def get_json_schema_log_file_path(data_model_path: str, source_node: str) -> str json_schema_log_file_path = f"{prefix}.{source_node}.schema.json" return json_schema_log_file_path + def export_graph(schema: dict, file_path: str) -> None: """Write object to a pickle file. Args: From 38b069082f050956639996884f3574f927254a66 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 5 Jun 2024 10:11:21 -0700 Subject: [PATCH 036/124] Return 0 for all convert, but echo the filepath created --- schematic/schemas/commands.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index d8b998be5..f3effa5b4 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -73,7 +73,7 @@ def convert( output_jsonld: Optional[str], output_type: Optional[str], output_path: Optional[str], -) -> str: +) -> int: """ Running CLI to convert data model specification in CSV format to data model in JSON-LD format. @@ -149,7 +149,8 @@ def convert( raise error if output_type == "graph": - return output_graph + click.echo(f"Graph created {output_graph}") + return 0 logger.info("Converting data model to JSON-LD") jsonld_data_model = convert_graph_to_jsonld(graph=graph_data_model) From 9907b4eb3edafdf311f476f4d54c366cbb8f7406 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 6 Jun 2024 10:00:41 -0700 Subject: [PATCH 037/124] Fix mix-up between parsed data model and graph data model --- schematic/visualization/attributes_explorer.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/schematic/visualization/attributes_explorer.py b/schematic/visualization/attributes_explorer.py index 28e8bdde4..e0c863ba5 100644 --- a/schematic/visualization/attributes_explorer.py +++ b/schematic/visualization/attributes_explorer.py @@ -34,6 +34,9 @@ def __init__( self.path_to_jsonld = path_to_jsonld self.jsonld = load_json(self.path_to_jsonld) + if data_model_graph_pickle: + with open(data_model_graph_pickle, 'rb') as f: + graph_data_model = pickle.load(f) # Parse Model if not parsed_data_model: @@ -42,10 +45,6 @@ def __init__( ) parsed_data_model = data_model_parser.parse_model() - if data_model_graph_pickle: - with open(data_model_graph_pickle, 'rb') as f: - parsed_data_model = pickle.load(f) - # Instantiate DataModelGraph if not data_model_grapher: data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) From 481ebd328bb5536f3e5857c57f70c660c80f4a90 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 6 Jun 2024 10:01:08 -0700 Subject: [PATCH 038/124] Add data model pickle parsing to tanlged_tree --- schematic/visualization/tangled_tree.py | 45 ++++++++++++------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/schematic/visualization/tangled_tree.py b/schematic/visualization/tangled_tree.py index 2b4a48b2b..f67cfebf6 100644 --- a/schematic/visualization/tangled_tree.py +++ b/schematic/visualization/tangled_tree.py @@ -52,37 +52,33 @@ def __init__( path_to_json_ld: str, figure_type: FigureType, data_model_labels: DisplayLabelType, - graph_data_model: Optional[nx.MultiDiGraph] = None, data_model_graph_pickle: Optional[str] = None, ) -> None: - if graph_data_model: - self.graph_data_model = graph_data_model - else: - # Load jsonld - self.path_to_json_ld = path_to_json_ld - self.json_data_model = load_json(self.path_to_json_ld) + # Load jsonld + self.path_to_json_ld = path_to_json_ld + self.json_data_model = load_json(self.path_to_json_ld) - # Parse schema name - self.schema_name = path.basename(self.path_to_json_ld).split(".model.jsonld")[0] + # Parse schema name + self.schema_name = path.basename(self.path_to_json_ld).split(".model.jsonld")[0] - # Instantiate Data Model Parser - if not data_model_graph_pickle: - data_model_parser = DataModelParser( - path_to_data_model=self.path_to_json_ld, - ) + # Instantiate Data Model Parser + if not data_model_graph_pickle: + data_model_parser = DataModelParser( + path_to_data_model=self.path_to_json_ld, + ) - # Parse Model - parsed_data_model = data_model_parser.parse_model() + # Parse Model + parsed_data_model = data_model_parser.parse_model() - # Instantiate DataModelGraph - data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) + # Instantiate DataModelGraph + data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) - # Generate graph - self.graph_data_model = data_model_grapher.graph + # Generate graph + self.graph_data_model = data_model_grapher.graph - else: - with open(data_model_graph_pickle, 'rb') as f: - self.graph_data_model = pickle.load(f) + else: + with open(data_model_graph_pickle, 'rb') as f: + self.graph_data_model = pickle.load(f) # Instantiate Data Model Graph Explorer self.dmge = DataModelGraphExplorer(self.graph_data_model) @@ -102,7 +98,8 @@ def __init__( data_model_grapher=data_model_grapher, data_model_graph_explorer=self.dmge, parsed_data_model=parsed_data_model, - graph_data_model=graph_data_model, + graph_data_model=self.graph_data_model, + data_model_graph_pickle=data_model_graph_pickle, ) # Create output paths. From f63231a8d6146774e5a1a3b6efee81cc7d0ca285 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 6 Jun 2024 10:01:28 -0700 Subject: [PATCH 039/124] Add data_model_pickle file to tests --- tests/test_viz.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_viz.py b/tests/test_viz.py index f40aca332..fea1bd185 100644 --- a/tests/test_viz.py +++ b/tests/test_viz.py @@ -17,15 +17,16 @@ def attributes_explorer(helpers): # Get JSONLD file path path_to_jsonld = helpers.get_data_path("example.model.jsonld") + path_to_graph = helpers.get_data_path("example.model.pickle") # Initialize TangledTree attributes_explorer = AttributesExplorer( path_to_jsonld, + data_model_graph_pickle=path_to_graph, data_model_labels="class_label", ) yield attributes_explorer - @pytest.fixture def tangled_tree(helpers): figure_type = "component" From f3fdc41ad2eb467e771cf9fb0651c1b2227c9162 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 6 Jun 2024 10:02:18 -0700 Subject: [PATCH 040/124] Add data model pickle file --- tests/data/example.model.pickle | Bin 0 -> 10290 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/data/example.model.pickle diff --git a/tests/data/example.model.pickle b/tests/data/example.model.pickle new file mode 100644 index 0000000000000000000000000000000000000000..116e0007ff998842d2187a7abe43fa8b57e829b1 GIT binary patch literal 10290 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 literal 0 HcmV?d00001 From 032771f04f8db709764126ec6e831c925c156aad Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 6 Jun 2024 10:03:07 -0700 Subject: [PATCH 041/124] run black --- schematic/visualization/attributes_explorer.py | 2 +- schematic/visualization/tangled_tree.py | 2 +- tests/test_viz.py | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/schematic/visualization/attributes_explorer.py b/schematic/visualization/attributes_explorer.py index e0c863ba5..75828000a 100644 --- a/schematic/visualization/attributes_explorer.py +++ b/schematic/visualization/attributes_explorer.py @@ -35,7 +35,7 @@ def __init__( self.jsonld = load_json(self.path_to_jsonld) if data_model_graph_pickle: - with open(data_model_graph_pickle, 'rb') as f: + with open(data_model_graph_pickle, "rb") as f: graph_data_model = pickle.load(f) # Parse Model diff --git a/schematic/visualization/tangled_tree.py b/schematic/visualization/tangled_tree.py index f67cfebf6..99cfcb1c4 100644 --- a/schematic/visualization/tangled_tree.py +++ b/schematic/visualization/tangled_tree.py @@ -77,7 +77,7 @@ def __init__( self.graph_data_model = data_model_grapher.graph else: - with open(data_model_graph_pickle, 'rb') as f: + with open(data_model_graph_pickle, "rb") as f: self.graph_data_model = pickle.load(f) # Instantiate Data Model Graph Explorer diff --git a/tests/test_viz.py b/tests/test_viz.py index fea1bd185..bc2984c71 100644 --- a/tests/test_viz.py +++ b/tests/test_viz.py @@ -27,6 +27,7 @@ def attributes_explorer(helpers): ) yield attributes_explorer + @pytest.fixture def tangled_tree(helpers): figure_type = "component" From bf0e9ba117b49ae3f854a112c9f53c434e1b0fc4 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 6 Jun 2024 10:26:44 -0700 Subject: [PATCH 042/124] fix a couple sonarcloud issues with the graph_data_model variable --- schematic/visualization/attributes_explorer.py | 2 +- schematic/visualization/tangled_tree.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/schematic/visualization/attributes_explorer.py b/schematic/visualization/attributes_explorer.py index 75828000a..3c3af7a94 100644 --- a/schematic/visualization/attributes_explorer.py +++ b/schematic/visualization/attributes_explorer.py @@ -34,7 +34,7 @@ def __init__( self.path_to_jsonld = path_to_jsonld self.jsonld = load_json(self.path_to_jsonld) - if data_model_graph_pickle: + if data_model_graph_pickle and not graph_data_model: with open(data_model_graph_pickle, "rb") as f: graph_data_model = pickle.load(f) diff --git a/schematic/visualization/tangled_tree.py b/schematic/visualization/tangled_tree.py index 99cfcb1c4..5eb402efe 100644 --- a/schematic/visualization/tangled_tree.py +++ b/schematic/visualization/tangled_tree.py @@ -53,6 +53,7 @@ def __init__( figure_type: FigureType, data_model_labels: DisplayLabelType, data_model_graph_pickle: Optional[str] = None, + graph_data_model: Optional[nx.MultiDiGraph] = None, ) -> None: # Load jsonld self.path_to_json_ld = path_to_json_ld From bc59218d0987c398d33b7c0de817785ef83ec2fd Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 6 Jun 2024 10:41:14 -0700 Subject: [PATCH 043/124] Add data_model_graph_pickle to metadata.py and tests --- schematic/models/metadata.py | 9 ++++++--- tests/test_metadata.py | 7 +++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/schematic/models/metadata.py b/schematic/models/metadata.py index 6317d8948..d1e3ca568 100644 --- a/schematic/models/metadata.py +++ b/schematic/models/metadata.py @@ -40,7 +40,7 @@ def __init__( inputMModelLocation: str, inputMModelLocationType: str, data_model_labels: str, - data_model_graph_pickle: Optional[str] = None + data_model_graph_pickle: Optional[str] = None, ) -> None: """Instantiates a MetadataModel object. @@ -61,10 +61,13 @@ def __init__( # Use graph, if provided. Otherwise parse data model for graph. if data_model_graph_pickle: - with open(data_model_graph_pickle, 'rb') as f: + with open(data_model_graph_pickle, "rb") as f: self.graph_data_model = pickle.load(f) + self.dmge = DataModelGraphExplorer(self.graph_data_model) else: - data_model_parser = DataModelParser(path_to_data_model=self.inputMModelLocation) + data_model_parser = DataModelParser( + path_to_data_model=self.inputMModelLocation + ) # Parse Model parsed_data_model = data_model_parser.parse_model() diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 8a2c2e965..9c1cd46ed 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -20,6 +20,7 @@ def metadata_model(helpers, data_model_labels): inputMModelLocation=helpers.get_data_path("example.model.jsonld"), data_model_labels=data_model_labels, inputMModelLocationType="local", + data_model_graph_pickle=helpers.get_data_path("example.model.pickle"), ) return metadata_model @@ -109,10 +110,12 @@ def test_populate_manifest(self, helpers, return_excel, data_model_labels): ids=["data_model_labels-display_label", "data_model_labels-class_label"], ) @pytest.mark.parametrize("validate_component", [None, "BulkRNA-seqAssay"]) - @pytest.mark.parametrize("temporary_file_copy", ["test_BulkRNAseq.csv"], indirect=True) + @pytest.mark.parametrize( + "temporary_file_copy", ["test_BulkRNAseq.csv"], indirect=True + ) def test_submit_metadata_manifest( self, - temporary_file_copy: Generator[str, None, None], + temporary_file_copy: Generator[str, None, None], helpers: Helpers, file_annotations_upload: bool, restrict_rules: bool, From 5973a75dac16b0a1c943eb02cf2fae0e87ce8170 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 6 Jun 2024 10:50:12 -0700 Subject: [PATCH 044/124] run black on generator.py --- schematic/manifest/generator.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/schematic/manifest/generator.py b/schematic/manifest/generator.py index 8adc51d21..75fc75bfc 100644 --- a/schematic/manifest/generator.py +++ b/schematic/manifest/generator.py @@ -1635,7 +1635,7 @@ def create_manifests( strict: Optional[bool] = True, use_annotations: Optional[bool] = False, graph_data_model: Optional[nx.MultiDiGraph] = None, - data_model_graph_pickle: str = None + data_model_graph_pickle: str = None, ) -> Union[List[str], List[pd.DataFrame]]: """Create multiple manifests @@ -1674,16 +1674,20 @@ def create_manifests( if not graph_data_model: if data_model_graph_pickle: - with open(data_model_graph_pickle, 'rb') as f: + with open(data_model_graph_pickle, "rb") as f: graph_data_model = pickle.load(f) else: - data_model_parser = DataModelParser(path_to_data_model=path_to_data_model) + data_model_parser = DataModelParser( + path_to_data_model=path_to_data_model + ) # Parse Model parsed_data_model = data_model_parser.parse_model() # Instantiate DataModelGraph - data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) + data_model_grapher = DataModelGraph( + parsed_data_model, data_model_labels + ) # Generate graph graph_data_model = data_model_grapher.graph From bf1a4495eb89328cdb55a8d01d9661a6227d2f71 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 6 Jun 2024 13:31:48 -0700 Subject: [PATCH 045/124] remove type check from networkx --- schematic/visualization/attributes_explorer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematic/visualization/attributes_explorer.py b/schematic/visualization/attributes_explorer.py index 3c3af7a94..9dcc61f3e 100644 --- a/schematic/visualization/attributes_explorer.py +++ b/schematic/visualization/attributes_explorer.py @@ -5,7 +5,7 @@ from typing import Optional, no_type_check import numpy as np import pandas as pd -import networkx as nx +import networkx as nx # type: ignore import pickle from schematic.schemas.data_model_parser import DataModelParser From 69bb182de269d9f594279738eec26dde8ef52a6f Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 6 Jun 2024 13:48:29 -0700 Subject: [PATCH 046/124] fix pylint issues --- schematic/visualization/attributes_explorer.py | 6 +++--- schematic/visualization/tangled_tree.py | 9 ++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/schematic/visualization/attributes_explorer.py b/schematic/visualization/attributes_explorer.py index 9dcc61f3e..23c55585c 100644 --- a/schematic/visualization/attributes_explorer.py +++ b/schematic/visualization/attributes_explorer.py @@ -2,11 +2,11 @@ import json import logging import os +import pickle from typing import Optional, no_type_check import numpy as np import pandas as pd import networkx as nx # type: ignore -import pickle from schematic.schemas.data_model_parser import DataModelParser from schematic.schemas.data_model_graph import DataModelGraph, DataModelGraphExplorer @@ -35,8 +35,8 @@ def __init__( self.jsonld = load_json(self.path_to_jsonld) if data_model_graph_pickle and not graph_data_model: - with open(data_model_graph_pickle, "rb") as f: - graph_data_model = pickle.load(f) + with open(data_model_graph_pickle, "rb") as file: + graph_data_model = pickle.load(file) # Parse Model if not parsed_data_model: diff --git a/schematic/visualization/tangled_tree.py b/schematic/visualization/tangled_tree.py index 5eb402efe..9b3d2efb2 100644 --- a/schematic/visualization/tangled_tree.py +++ b/schematic/visualization/tangled_tree.py @@ -8,9 +8,9 @@ import logging import os from os import path +import pickle from typing import Optional, Literal, TypedDict, Union from typing_extensions import assert_never -import pickle import networkx as nx # type: ignore from networkx.classes.reportviews import NodeView, EdgeDataView # type: ignore @@ -44,7 +44,7 @@ class Node(TypedDict): children: list[str] -class TangledTree: # pylint: disable=too-many-instance-attributes +class TangledTree: # pylint: disable=too-many-instance-attributes disable=too-many-arguments """Tangled tree class""" def __init__( @@ -53,7 +53,6 @@ def __init__( figure_type: FigureType, data_model_labels: DisplayLabelType, data_model_graph_pickle: Optional[str] = None, - graph_data_model: Optional[nx.MultiDiGraph] = None, ) -> None: # Load jsonld self.path_to_json_ld = path_to_json_ld @@ -78,8 +77,8 @@ def __init__( self.graph_data_model = data_model_grapher.graph else: - with open(data_model_graph_pickle, "rb") as f: - self.graph_data_model = pickle.load(f) + with open(data_model_graph_pickle, "rb") as file: + self.graph_data_model = pickle.load(file) # Instantiate Data Model Graph Explorer self.dmge = DataModelGraphExplorer(self.graph_data_model) From d93aa9d825a8117db5f5acbc45a2815c360e1668 Mon Sep 17 00:00:00 2001 From: afwillia Date: Fri, 7 Jun 2024 08:36:57 -0700 Subject: [PATCH 047/124] remove pickle from metadata test because it wasn't created with data_model_labels=display_label --- tests/test_metadata.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 9c1cd46ed..bf0c4d97b 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -20,7 +20,6 @@ def metadata_model(helpers, data_model_labels): inputMModelLocation=helpers.get_data_path("example.model.jsonld"), data_model_labels=data_model_labels, inputMModelLocationType="local", - data_model_graph_pickle=helpers.get_data_path("example.model.pickle"), ) return metadata_model From aef4f621327ceedb50af3828c13923e23022fc36 Mon Sep 17 00:00:00 2001 From: afwillia Date: Fri, 7 Jun 2024 09:39:43 -0700 Subject: [PATCH 048/124] create two metadata_model objects with different data_model_label graph files --- tests/test_metadata.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/test_metadata.py b/tests/test_metadata.py index bf0c4d97b..d1c876533 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -20,6 +20,20 @@ def metadata_model(helpers, data_model_labels): inputMModelLocation=helpers.get_data_path("example.model.jsonld"), data_model_labels=data_model_labels, inputMModelLocationType="local", + data_model_graph_pickle=helpers.get_data_path("example.model.pickle"), + ) + + return metadata_model + + +def metadata_model_display(helpers, data_model_labels): + metadata_model = MetadataModel( + inputMModelLocation=helpers.get_data_path("example.model.jsonld"), + data_model_labels=data_model_labels, + inputMModelLocationType="local", + data_model_graph_pickle=helpers.get_data_path( + "example.display.label.model.pickle" + ), ) return metadata_model @@ -34,7 +48,10 @@ class TestMetadataModel: ) def test_get_component_requirements(self, helpers, as_graph, data_model_labels): # Instantiate MetadataModel - meta_data_model = metadata_model(helpers, data_model_labels) + if data_model_labels == "class_label": + meta_data_model = metadata_model(helpers, data_model_labels) + else: + meta_data_model = metadata_model_display(helpers, data_model_labels) if data_model_labels == "display_label": source_component = "BulkRNAseqAssay" From 08b2ae589da46d3c51d3c6ac6e7cfe2a32edf31a Mon Sep 17 00:00:00 2001 From: afwillia Date: Fri, 7 Jun 2024 10:40:20 -0700 Subject: [PATCH 049/124] add display_label graph pickle --- tests/data/example.display.label.model.pickle | Bin 0 -> 11359 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/data/example.display.label.model.pickle diff --git a/tests/data/example.display.label.model.pickle b/tests/data/example.display.label.model.pickle new file mode 100644 index 0000000000000000000000000000000000000000..45f3957eebefa7e1b949150b7fcd3d359f575251 GIT binary patch literal 11359 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 literal 0 HcmV?d00001 From 68672c3a23d3f20879f8bdfcf631b4c0a67a1088 Mon Sep 17 00:00:00 2001 From: afwillia Date: Fri, 28 Jun 2024 11:57:38 -0700 Subject: [PATCH 050/124] Add multiple combinations of jsonld and pickle to test_viz attribute_explorer --- tests/test_viz.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/tests/test_viz.py b/tests/test_viz.py index bc2984c71..4d79ce093 100644 --- a/tests/test_viz.py +++ b/tests/test_viz.py @@ -12,19 +12,30 @@ logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger(__name__) - -@pytest.fixture -def attributes_explorer(helpers): +@pytest.fixture(params=[ + ("example.model.jsonld", "example.model.pickle"), + ("example.model.jsonld", ""), + pytest.param(("", ""), marks = pytest.mark.xfail), + pytest.param(("", "example.model.pickle"), marks = pytest.mark.xfail) +]) +def attributes_explorer(request, helpers): # Get JSONLD file path - path_to_jsonld = helpers.get_data_path("example.model.jsonld") - path_to_graph = helpers.get_data_path("example.model.pickle") + param1, param2 = request.param + path_to_jsonld = helpers.get_data_path(param1) + path_to_graph = helpers.get_data_path(param2) # Initialize TangledTree - attributes_explorer = AttributesExplorer( - path_to_jsonld, - data_model_graph_pickle=path_to_graph, - data_model_labels="class_label", - ) + if param2 != "": + attributes_explorer = AttributesExplorer( + path_to_jsonld, + data_model_graph_pickle=path_to_graph, + data_model_labels="class_label", + ) + else: + attributes_explorer = AttributesExplorer( + path_to_jsonld, + data_model_labels="class_label", + ) yield attributes_explorer From de07c558dbe6d8aa1d8667c124920b07da3dc085 Mon Sep 17 00:00:00 2001 From: afwillia Date: Fri, 28 Jun 2024 12:17:10 -0700 Subject: [PATCH 051/124] Fix missing variables in tangled_tree when jsonld and pickle are supplied --- schematic/visualization/tangled_tree.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/schematic/visualization/tangled_tree.py b/schematic/visualization/tangled_tree.py index 9b3d2efb2..822f58e1d 100644 --- a/schematic/visualization/tangled_tree.py +++ b/schematic/visualization/tangled_tree.py @@ -61,6 +61,8 @@ def __init__( # Parse schema name self.schema_name = path.basename(self.path_to_json_ld).split(".model.jsonld")[0] + parsed_data_model = None + # Instantiate Data Model Parser if not data_model_graph_pickle: data_model_parser = DataModelParser( @@ -79,6 +81,7 @@ def __init__( else: with open(data_model_graph_pickle, "rb") as file: self.graph_data_model = pickle.load(file) + data_model_grapher = self.graph_data_model # Instantiate Data Model Graph Explorer self.dmge = DataModelGraphExplorer(self.graph_data_model) From 77f5ec4b089ab2698eaf1217401f06a96b6698a8 Mon Sep 17 00:00:00 2001 From: afwillia Date: Fri, 28 Jun 2024 12:17:29 -0700 Subject: [PATCH 052/124] Add combinations of jsonld and pickle to tangled_tree tests --- tests/test_viz.py | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/tests/test_viz.py b/tests/test_viz.py index 4d79ce093..e17c80c87 100644 --- a/tests/test_viz.py +++ b/tests/test_viz.py @@ -38,21 +38,36 @@ def attributes_explorer(request, helpers): ) yield attributes_explorer - -@pytest.fixture -def tangled_tree(helpers): +@pytest.fixture(params=[ + ("example.model.jsonld", "example.model.pickle"), + ("example.model.jsonld", ""), + pytest.param(("", ""), marks = pytest.mark.xfail), + pytest.param(("", "example.model.pickle"), marks = pytest.mark.xfail) +]) +def tangled_tree(helpers, request): figure_type = "component" # Get JSONLD file path - path_to_jsonld = helpers.get_data_path("example.model.jsonld") + param1, param2 = request.param + path_to_jsonld = helpers.get_data_path(param1) + path_to_graph = helpers.get_data_path(param2) # Initialize TangledTree - tangled_tree = TangledTree( - path_to_jsonld, figure_type, data_model_labels="class_label" - ) + if param2 == "": + tangled_tree = TangledTree( + path_to_jsonld, + figure_type, + data_model_labels="class_label" + ) + else: + tangled_tree = TangledTree( + path_to_jsonld, + figure_type, + data_model_labels="class_label", + data_model_graph_pickle = path_to_graph + ) yield tangled_tree - class TestVisualization: def test_ae(self, helpers, attributes_explorer): attributes_str = attributes_explorer.parse_attributes(save_file=False) From 5934ed5a66791fc42b0765f8facce9b26f105b5a Mon Sep 17 00:00:00 2001 From: afwillia Date: Fri, 28 Jun 2024 12:27:39 -0700 Subject: [PATCH 053/124] add graph_data_model argument description --- schematic/manifest/generator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/schematic/manifest/generator.py b/schematic/manifest/generator.py index da91d1f4f..e095898ea 100644 --- a/schematic/manifest/generator.py +++ b/schematic/manifest/generator.py @@ -1651,6 +1651,7 @@ def create_manifests( Args: path_to_data_model (str): str path to data model data_model_graph_pickle (str): A data model graph as csv or pickle + graph_data_model (str): An networkx MultiDiGraph object data_types (list): a list of data types access_token (str, optional): synapse access token. Required when getting an existing manifest. Defaults to None. dataset_ids (list, optional): a list of dataset ids when generating an existing manifest. Defaults to None. From 51313bd98b056ef4b4230070ed252bd1e6ba81ee Mon Sep 17 00:00:00 2001 From: afwillia Date: Fri, 28 Jun 2024 12:28:57 -0700 Subject: [PATCH 054/124] add data_model_graph_pickle description to MetadataModel --- schematic/models/metadata.py | 1 + 1 file changed, 1 insertion(+) diff --git a/schematic/models/metadata.py b/schematic/models/metadata.py index e9e250cf9..cf9b978ef 100644 --- a/schematic/models/metadata.py +++ b/schematic/models/metadata.py @@ -50,6 +50,7 @@ def __init__( Args: inputMModelLocation: local path, uri, synapse entity id (e.g. gs://, syn123, /User/x/…); present location inputMModelLocationType: specifier to indicate where the metadata model resource can be found (e.g. 'local' if file/JSON-LD is on local machine) + data_model_graph_pickle: filepath to a data model graph stored as pickle file. """ # extract extension of 'inputMModelLocation' # ensure that it is necessarily pointing to a '.jsonld' file From e4e13680a1b2393234737f81b85e4b1746a4588a Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 26 Aug 2024 09:50:52 -0700 Subject: [PATCH 055/124] run black on test_viz.py --- tests/test_viz.py | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/tests/test_viz.py b/tests/test_viz.py index e17c80c87..2a0e90827 100644 --- a/tests/test_viz.py +++ b/tests/test_viz.py @@ -12,12 +12,15 @@ logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger(__name__) -@pytest.fixture(params=[ - ("example.model.jsonld", "example.model.pickle"), - ("example.model.jsonld", ""), - pytest.param(("", ""), marks = pytest.mark.xfail), - pytest.param(("", "example.model.pickle"), marks = pytest.mark.xfail) -]) + +@pytest.fixture( + params=[ + ("example.model.jsonld", "example.model.pickle"), + ("example.model.jsonld", ""), + pytest.param(("", ""), marks=pytest.mark.xfail), + pytest.param(("", "example.model.pickle"), marks=pytest.mark.xfail), + ] +) def attributes_explorer(request, helpers): # Get JSONLD file path param1, param2 = request.param @@ -38,12 +41,15 @@ def attributes_explorer(request, helpers): ) yield attributes_explorer -@pytest.fixture(params=[ - ("example.model.jsonld", "example.model.pickle"), - ("example.model.jsonld", ""), - pytest.param(("", ""), marks = pytest.mark.xfail), - pytest.param(("", "example.model.pickle"), marks = pytest.mark.xfail) -]) + +@pytest.fixture( + params=[ + ("example.model.jsonld", "example.model.pickle"), + ("example.model.jsonld", ""), + pytest.param(("", ""), marks=pytest.mark.xfail), + pytest.param(("", "example.model.pickle"), marks=pytest.mark.xfail), + ] +) def tangled_tree(helpers, request): figure_type = "component" @@ -55,19 +61,18 @@ def tangled_tree(helpers, request): # Initialize TangledTree if param2 == "": tangled_tree = TangledTree( - path_to_jsonld, - figure_type, - data_model_labels="class_label" + path_to_jsonld, figure_type, data_model_labels="class_label" ) else: tangled_tree = TangledTree( path_to_jsonld, figure_type, data_model_labels="class_label", - data_model_graph_pickle = path_to_graph + data_model_graph_pickle=path_to_graph, ) yield tangled_tree + class TestVisualization: def test_ae(self, helpers, attributes_explorer): attributes_str = attributes_explorer.parse_attributes(save_file=False) From 9a78a18a8dac13d89916da8c9625b676628235e6 Mon Sep 17 00:00:00 2001 From: Anthony Williams Date: Mon, 26 Aug 2024 13:38:45 -0700 Subject: [PATCH 056/124] Update schematic/manifest/generator.py Co-authored-by: BryanFauble <17128019+BryanFauble@users.noreply.github.com> --- schematic/manifest/generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematic/manifest/generator.py b/schematic/manifest/generator.py index e095898ea..811876d37 100644 --- a/schematic/manifest/generator.py +++ b/schematic/manifest/generator.py @@ -1644,7 +1644,7 @@ def create_manifests( strict: Optional[bool] = True, use_annotations: Optional[bool] = False, graph_data_model: Optional[nx.MultiDiGraph] = None, - data_model_graph_pickle: str = None, + data_model_graph_pickle: Optional[str] = None, ) -> Union[List[str], List[pd.DataFrame]]: """Create multiple manifests From 05b4fe081e1456c73ee2119a38ffaf9323519537 Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 26 Aug 2024 14:05:39 -0700 Subject: [PATCH 057/124] Add read_pickle function to read a binary pickle file --- schematic/utils/io_utils.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/schematic/utils/io_utils.py b/schematic/utils/io_utils.py index 1651d085e..bfa088d0c 100644 --- a/schematic/utils/io_utils.py +++ b/schematic/utils/io_utils.py @@ -4,6 +4,7 @@ import json import urllib.request from schematic import LOADER +import pickle def load_json(file_path: str) -> Any: @@ -40,3 +41,9 @@ def load_schemaorg() -> Any: data_path = "data_models/schema_org.model.jsonld" schema_org_path = LOADER.filename(data_path) return load_json(schema_org_path) + +def read_pickle(): + """Read pickle file""" + with open(file_path, "rb") as fle: + data = pickle.load(fle) + return data From 0964501431fb3ab56048e1b481de38904f211275 Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 26 Aug 2024 14:06:15 -0700 Subject: [PATCH 058/124] Use read_pickle instead of importing pickle and opening file --- schematic/manifest/generator.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/schematic/manifest/generator.py b/schematic/manifest/generator.py index 811876d37..d64f9f9d8 100644 --- a/schematic/manifest/generator.py +++ b/schematic/manifest/generator.py @@ -11,7 +11,6 @@ import pygsheets as ps from tempfile import NamedTemporaryFile from typing import Any, Dict, List, Optional, Tuple, Union, BinaryIO, Literal -import pickle from schematic.schemas.data_model_graph import DataModelGraph, DataModelGraphExplorer from schematic.schemas.data_model_parser import DataModelParser @@ -22,6 +21,7 @@ build_service_account_creds, ) from schematic.utils.df_utils import update_df, load_df +from schematic.utils.io_utils import read_pickle from schematic.utils.schema_utils import extract_component_validation_rules from schematic.utils.validate_utils import rule_in_rule_list from schematic.utils.schema_utils import DisplayLabelType @@ -1684,8 +1684,7 @@ def create_manifests( if not graph_data_model: if data_model_graph_pickle: - with open(data_model_graph_pickle, "rb") as f: - graph_data_model = pickle.load(f) + graph_data_model = read_pickle(data_model_graph_pickle) else: data_model_parser = DataModelParser( path_to_data_model=path_to_data_model From 697cc3e077b628f214111a88692b9ba8ed6c55c1 Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 26 Aug 2024 14:12:23 -0700 Subject: [PATCH 059/124] Add note for pickle files that don't fit in memory. Not sure if this will ever be an issue --- schematic/manifest/generator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/schematic/manifest/generator.py b/schematic/manifest/generator.py index d64f9f9d8..23a668876 100644 --- a/schematic/manifest/generator.py +++ b/schematic/manifest/generator.py @@ -1684,6 +1684,7 @@ def create_manifests( if not graph_data_model: if data_model_graph_pickle: + """What if pickle file does not fit in memory?""" graph_data_model = read_pickle(data_model_graph_pickle) else: data_model_parser = DataModelParser( From 774dc916f47426abf59b71385e6ede4ce4169167 Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 26 Aug 2024 14:12:55 -0700 Subject: [PATCH 060/124] Use read_pickle to load the pickle file in metadata.py --- schematic/models/metadata.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/schematic/models/metadata.py b/schematic/models/metadata.py index cf9b978ef..bfc56ada0 100644 --- a/schematic/models/metadata.py +++ b/schematic/models/metadata.py @@ -3,7 +3,6 @@ import networkx as nx from os.path import exists from jsonschema import ValidationError -import pickle # allows specifying explicit variable types from typing import Any, Dict, Optional, Text, List @@ -18,6 +17,7 @@ from schematic.store.synapse import SynapseStorage from schematic.utils.df_utils import load_df +from schematic.utils.io_utils import read_pickle from schematic.models.validate_manifest import validate_all from opentelemetry import trace @@ -65,8 +65,7 @@ def __init__( # Use graph, if provided. Otherwise parse data model for graph. if data_model_graph_pickle: - with open(data_model_graph_pickle, "rb") as f: - self.graph_data_model = pickle.load(f) + self.graph_data_model = read_pickle(data_model_graph_pickle) self.dmge = DataModelGraphExplorer(self.graph_data_model) else: data_model_parser = DataModelParser( From bb7c4502d3a68f9352bfccf4da5aa652b611b297 Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 26 Aug 2024 14:18:28 -0700 Subject: [PATCH 061/124] read_pickle instead of import pickle in attributes_explorer --- schematic/visualization/attributes_explorer.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/schematic/visualization/attributes_explorer.py b/schematic/visualization/attributes_explorer.py index 23c55585c..e768d1ab6 100644 --- a/schematic/visualization/attributes_explorer.py +++ b/schematic/visualization/attributes_explorer.py @@ -2,7 +2,6 @@ import json import logging import os -import pickle from typing import Optional, no_type_check import numpy as np import pandas as pd @@ -12,7 +11,7 @@ from schematic.schemas.data_model_graph import DataModelGraph, DataModelGraphExplorer from schematic.schemas.data_model_json_schema import DataModelJSONSchema from schematic.utils.schema_utils import DisplayLabelType -from schematic.utils.io_utils import load_json +from schematic.utils.io_utils import load_json, read_pickle logger = logging.getLogger(__name__) @@ -35,8 +34,7 @@ def __init__( self.jsonld = load_json(self.path_to_jsonld) if data_model_graph_pickle and not graph_data_model: - with open(data_model_graph_pickle, "rb") as file: - graph_data_model = pickle.load(file) + graph_data_model = read_pickle(data_model_graph_pickle) # Parse Model if not parsed_data_model: From 8f5bc1a8f5063b42cc0831baabc5f2bc85714d4e Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 26 Aug 2024 14:29:53 -0700 Subject: [PATCH 062/124] set self.graph_data_model and update it if data_model_grapher is not provided --- schematic/visualization/attributes_explorer.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/schematic/visualization/attributes_explorer.py b/schematic/visualization/attributes_explorer.py index e768d1ab6..5fbc2c210 100644 --- a/schematic/visualization/attributes_explorer.py +++ b/schematic/visualization/attributes_explorer.py @@ -34,7 +34,7 @@ def __init__( self.jsonld = load_json(self.path_to_jsonld) if data_model_graph_pickle and not graph_data_model: - graph_data_model = read_pickle(data_model_graph_pickle) + self.graph_data_model = read_pickle(data_model_graph_pickle) # Parse Model if not parsed_data_model: @@ -46,9 +46,8 @@ def __init__( # Instantiate DataModelGraph if not data_model_grapher: data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) - - # Generate graph - self.graph_data_model = data_model_grapher.graph + # Generate graph + self.graph_data_model = data_model_grapher.graph # Instantiate Data Model Graph Explorer if not data_model_graph_explorer: From 35c13ddaac04350c0c14c5c8d6c456e97fe95593 Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 26 Aug 2024 14:33:03 -0700 Subject: [PATCH 063/124] use if ... is not None instead of if not ... --- schematic/visualization/attributes_explorer.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/schematic/visualization/attributes_explorer.py b/schematic/visualization/attributes_explorer.py index 5fbc2c210..30d32fbba 100644 --- a/schematic/visualization/attributes_explorer.py +++ b/schematic/visualization/attributes_explorer.py @@ -33,24 +33,24 @@ def __init__( self.path_to_jsonld = path_to_jsonld self.jsonld = load_json(self.path_to_jsonld) - if data_model_graph_pickle and not graph_data_model: + if data_model_graph_pickle and graph_data_model is not None: self.graph_data_model = read_pickle(data_model_graph_pickle) # Parse Model - if not parsed_data_model: + if parsed_data_model is not None: data_model_parser = DataModelParser( path_to_data_model=self.path_to_jsonld, ) parsed_data_model = data_model_parser.parse_model() # Instantiate DataModelGraph - if not data_model_grapher: + if data_model_grapher is not None: data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) # Generate graph self.graph_data_model = data_model_grapher.graph # Instantiate Data Model Graph Explorer - if not data_model_graph_explorer: + if data_model_graph_explorer is not None: self.dmge = DataModelGraphExplorer(self.graph_data_model) else: self.dmge = data_model_graph_explorer From f8c14d41958cedc44277815949a9b3f048616a6a Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 26 Aug 2024 15:42:13 -0700 Subject: [PATCH 064/124] use if ... is not None instead of if not ... --- schematic/visualization/tangled_tree.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematic/visualization/tangled_tree.py b/schematic/visualization/tangled_tree.py index 822f58e1d..8d45b764b 100644 --- a/schematic/visualization/tangled_tree.py +++ b/schematic/visualization/tangled_tree.py @@ -64,7 +64,7 @@ def __init__( parsed_data_model = None # Instantiate Data Model Parser - if not data_model_graph_pickle: + if data_model_graph_pickle is not None: data_model_parser = DataModelParser( path_to_data_model=self.path_to_json_ld, ) From 13c9ffc50608f65d803e9bb228aafc7c954253b9 Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 26 Aug 2024 15:46:23 -0700 Subject: [PATCH 065/124] add an input to read_pickle --- schematic/utils/io_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematic/utils/io_utils.py b/schematic/utils/io_utils.py index bfa088d0c..107fd47b8 100644 --- a/schematic/utils/io_utils.py +++ b/schematic/utils/io_utils.py @@ -42,7 +42,7 @@ def load_schemaorg() -> Any: schema_org_path = LOADER.filename(data_path) return load_json(schema_org_path) -def read_pickle(): +def read_pickle(file_path: str) -> Any: """Read pickle file""" with open(file_path, "rb") as fle: data = pickle.load(fle) From 9205d6d9e70ee3516886d23093c14a06fa1753b6 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 07:27:40 -0700 Subject: [PATCH 066/124] run black on io_utils.py --- schematic/utils/io_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/schematic/utils/io_utils.py b/schematic/utils/io_utils.py index 107fd47b8..175ed60db 100644 --- a/schematic/utils/io_utils.py +++ b/schematic/utils/io_utils.py @@ -42,6 +42,7 @@ def load_schemaorg() -> Any: schema_org_path = LOADER.filename(data_path) return load_json(schema_org_path) + def read_pickle(file_path: str) -> Any: """Read pickle file""" with open(file_path, "rb") as fle: From 172e1b129e7dcfd4ecd5d4a4b712d84f28eb6b5a Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 08:02:29 -0700 Subject: [PATCH 067/124] use read_pickle to read pickle file. Set default data_model_labels --- schematic/visualization/tangled_tree.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/schematic/visualization/tangled_tree.py b/schematic/visualization/tangled_tree.py index 8d45b764b..fdaf18151 100644 --- a/schematic/visualization/tangled_tree.py +++ b/schematic/visualization/tangled_tree.py @@ -8,7 +8,6 @@ import logging import os from os import path -import pickle from typing import Optional, Literal, TypedDict, Union from typing_extensions import assert_never @@ -19,7 +18,7 @@ from schematic.visualization.attributes_explorer import AttributesExplorer from schematic.schemas.data_model_parser import DataModelParser from schematic.schemas.data_model_graph import DataModelGraph, DataModelGraphExplorer -from schematic.utils.io_utils import load_json +from schematic.utils.io_utils import load_json, read_pickle from schematic.utils.schema_utils import DisplayLabelType @@ -51,7 +50,7 @@ def __init__( self, path_to_json_ld: str, figure_type: FigureType, - data_model_labels: DisplayLabelType, + data_model_labels: DisplayLabelType = "class_label", data_model_graph_pickle: Optional[str] = None, ) -> None: # Load jsonld @@ -79,9 +78,8 @@ def __init__( self.graph_data_model = data_model_grapher.graph else: - with open(data_model_graph_pickle, "rb") as file: - self.graph_data_model = pickle.load(file) - data_model_grapher = self.graph_data_model + self.graph_data_model = read_pickle(data_model_graph_pickle) + data_model_grapher = self.graph_data_model # Instantiate Data Model Graph Explorer self.dmge = DataModelGraphExplorer(self.graph_data_model) From d4d3a30e14aed8568d46a93adff9da3f7956b6f7 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 08:02:46 -0700 Subject: [PATCH 068/124] set default data_model_labels --- schematic/visualization/attributes_explorer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematic/visualization/attributes_explorer.py b/schematic/visualization/attributes_explorer.py index 30d32fbba..bcebb74de 100644 --- a/schematic/visualization/attributes_explorer.py +++ b/schematic/visualization/attributes_explorer.py @@ -23,7 +23,7 @@ class AttributesExplorer: def __init__( self, path_to_jsonld: str, - data_model_labels: DisplayLabelType, + data_model_labels: DisplayLabelType = "class_label", data_model_grapher: Optional[DataModelGraph] = None, data_model_graph_explorer: Optional[DataModelGraphExplorer] = None, parsed_data_model: Optional[dict] = None, From 730b227f468bc6e99eb886f2e7572ef8f9795f1d Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 08:29:38 -0700 Subject: [PATCH 069/124] alter logic for setting graph_data_model from pickle or DataModelGraph object --- schematic/visualization/attributes_explorer.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/schematic/visualization/attributes_explorer.py b/schematic/visualization/attributes_explorer.py index bcebb74de..f9149f9a1 100644 --- a/schematic/visualization/attributes_explorer.py +++ b/schematic/visualization/attributes_explorer.py @@ -33,7 +33,9 @@ def __init__( self.path_to_jsonld = path_to_jsonld self.jsonld = load_json(self.path_to_jsonld) - if data_model_graph_pickle and graph_data_model is not None: + if graph_data_model is not None: + self.graph_data_model = graph_data_model + elif data_model_graph_pickle is not None: self.graph_data_model = read_pickle(data_model_graph_pickle) # Parse Model From 795e2637b811785dc13a1b1fbd5b8d34334f6b19 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 08:35:43 -0700 Subject: [PATCH 070/124] fix pickle reading logic in tangled tree --- schematic/visualization/tangled_tree.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematic/visualization/tangled_tree.py b/schematic/visualization/tangled_tree.py index fdaf18151..782bffef5 100644 --- a/schematic/visualization/tangled_tree.py +++ b/schematic/visualization/tangled_tree.py @@ -63,7 +63,7 @@ def __init__( parsed_data_model = None # Instantiate Data Model Parser - if data_model_graph_pickle is not None: + if data_model_graph_pickle is None: data_model_parser = DataModelParser( path_to_data_model=self.path_to_json_ld, ) From 0ddb552c6ba220e4578ef2aef22723fe23a87658 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 08:37:25 -0700 Subject: [PATCH 071/124] fix logic checking for None parameters in attributes_explorer.py --- schematic/visualization/attributes_explorer.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/schematic/visualization/attributes_explorer.py b/schematic/visualization/attributes_explorer.py index f9149f9a1..abc5a0e2b 100644 --- a/schematic/visualization/attributes_explorer.py +++ b/schematic/visualization/attributes_explorer.py @@ -39,23 +39,23 @@ def __init__( self.graph_data_model = read_pickle(data_model_graph_pickle) # Parse Model - if parsed_data_model is not None: + if parsed_data_model is None: data_model_parser = DataModelParser( path_to_data_model=self.path_to_jsonld, ) parsed_data_model = data_model_parser.parse_model() # Instantiate DataModelGraph - if data_model_grapher is not None: + if data_model_grapher is None: data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) # Generate graph self.graph_data_model = data_model_grapher.graph # Instantiate Data Model Graph Explorer if data_model_graph_explorer is not None: - self.dmge = DataModelGraphExplorer(self.graph_data_model) - else: self.dmge = data_model_graph_explorer + else: + self.dmge = DataModelGraphExplorer(self.graph_data_model) # Instantiate Data Model Json Schema self.data_model_js = DataModelJSONSchema( From 537af6fcee7b2a698282148374f1242ad5f48768 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 08:42:59 -0700 Subject: [PATCH 072/124] import "import pickle" should be placed before "from schematic import LOADER" --- schematic/utils/io_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematic/utils/io_utils.py b/schematic/utils/io_utils.py index 175ed60db..61b413dbe 100644 --- a/schematic/utils/io_utils.py +++ b/schematic/utils/io_utils.py @@ -3,8 +3,8 @@ from typing import Any import json import urllib.request -from schematic import LOADER import pickle +from schematic import LOADER def load_json(file_path: str) -> Any: From dcb2f65dea1790b4d6a66047c69ef83243106d50 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 09:14:04 -0700 Subject: [PATCH 073/124] Use literal for output_type parameter and remove unnecessary try/except statement --- schematic/schemas/commands.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index f3effa5b4..55539ef35 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -71,7 +71,7 @@ def convert( schema: Any, data_model_labels: DisplayLabelType, output_jsonld: Optional[str], - output_type: Optional[str], + output_type: Optional[Literal["jsonld", "graph", "all"]], output_path: Optional[str], ) -> int: """ @@ -143,10 +143,7 @@ def convert( if output_type in ["graph", "all"]: logger.info("Export graph to pickle.") output_graph = output_file_no_ext + ".pickle" - try: - export_graph(graph_data_model, output_graph) - except SystemExit as error: - raise error + export_graph(graph_data_model, output_graph) if output_type == "graph": click.echo(f"Graph created {output_graph}") From bb4ee3a82730a17c894b4d20a9ffeec7317ede34 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 09:14:22 -0700 Subject: [PATCH 074/124] use logger.exception instead of logger.error --- schematic/utils/schema_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematic/utils/schema_utils.py b/schematic/utils/schema_utils.py index 3c9af0ef8..a0b260835 100644 --- a/schematic/utils/schema_utils.py +++ b/schematic/utils/schema_utils.py @@ -514,7 +514,7 @@ def export_graph(schema: dict, file_path: str) -> None: pickle.dump(schema, file) logger.info(f"The graph was created and saved to '{file_path}'.") except SystemExit as error: - logger.error( + logger.exception( f"The graph failed to save to '{file_path}'. Please check your file path again." ) raise error From 5504586a3ce67a0909d559d7580a31f4fcc70a29 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 09:17:48 -0700 Subject: [PATCH 075/124] move return statement inside the output_type check block --- schematic/schemas/commands.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index 55539ef35..86f121a04 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -144,10 +144,9 @@ def convert( logger.info("Export graph to pickle.") output_graph = output_file_no_ext + ".pickle" export_graph(graph_data_model, output_graph) - - if output_type == "graph": - click.echo(f"Graph created {output_graph}") - return 0 + if output_type == "graph": + click.echo(f"Graph created {output_graph}") + return 0 logger.info("Converting data model to JSON-LD") jsonld_data_model = convert_graph_to_jsonld(graph=graph_data_model) From b88ee860bb47d16ad88bb2759c152a566e2385f8 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 09:37:48 -0700 Subject: [PATCH 076/124] run black --- tests/test_cli.py | 59 +++++++++++------------------------------------ 1 file changed, 13 insertions(+), 46 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 34be14ed2..6aca1535f 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -50,56 +50,31 @@ def assert_expected_file(self, result, output_path): @pytest.mark.parametrize( "output_path", - [ - "tests/data/example.model.pickle", - "tests/data/example.model.jsonld" - ], - ids=["output_path_pickle", "output_path_jsonld"] + ["tests/data/example.model.pickle", "tests/data/example.model.jsonld"], + ids=["output_path_pickle", "output_path_jsonld"], ) @pytest.mark.parametrize( "output_type", - [ - "jsonld", - "graph", - "all" - ], - ids=["output_type_jsonld", "output_type_graph", "output_type_all"] + ["jsonld", "graph", "all"], + ids=["output_type_jsonld", "output_type_graph", "output_type_all"], ) def test_schema_convert_cli(self, runner, output_path, output_type): model = "tests/data/example.model.csv" label_type = "class_label" expected = 0 - resultOne = runner.invoke( - schema, - [ - "convert", - model - ] - ) + resultOne = runner.invoke(schema, ["convert", model]) assert resultOne.exit_code == expected resultTwo = runner.invoke( - schema, - [ - "convert", - model, - "--output_path", - output_path - ] + schema, ["convert", model, "--output_path", output_path] ) assert resultTwo.exit_code == expected resultThree = runner.invoke( - schema, - [ - "convert", - model, - "--output_type", - output_type - ] + schema, ["convert", model, "--output_type", output_type] ) assert resultThree.exit_code == expected @@ -112,8 +87,8 @@ def test_schema_convert_cli(self, runner, output_path, output_type): "--output_type", output_type, "--output_jsonld", - output_path - ] + output_path, + ], ) assert resultFour.exit_code == expected @@ -127,7 +102,7 @@ def test_schema_convert_cli(self, runner, output_path, output_type): output_path, "--data_model_labels", label_type, - ] + ], ) assert result.exit_code == expected @@ -140,22 +115,14 @@ def test_schema_convert_cli(self, runner, output_path, output_type): "--output_jsonld", "tests/data/example.model.pickle", "--output_path", - "tests/data/example.model.pickle" - ] + "tests/data/example.model.pickle", + ], ) assert resultFive.exit_code == expected resultSix = runner.invoke( - schema, - [ - "convert", - model, - "--output_jsonld", - "", - "--output_path", - "" - ] + schema, ["convert", model, "--output_jsonld", "", "--output_path", ""] ) assert resultSix.exit_code == expected From 2bf450b4bb7da01994387ebeff3be494a813a7f5 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 09:46:27 -0700 Subject: [PATCH 077/124] import Literal from typing --- schematic/schemas/commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index 86f121a04..8250ff247 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -3,7 +3,7 @@ import logging import time import re -from typing import get_args, Optional, Any +from typing import get_args, Optional, Any, Literal import click import click_log # type: ignore From 7adaf445c360b8d71649055e66dad9deec6e685d Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 10:58:42 -0700 Subject: [PATCH 078/124] add tests for export_graph --- tests/test_utils.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/test_utils.py b/tests/test_utils.py index 1ff72d673..425312c53 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -47,6 +47,7 @@ from schematic.utils import cli_utils, df_utils, general, io_utils, validate_utils from schematic.utils.df_utils import load_df +import pickle from schematic.utils.general import ( calculate_datetime, check_synapse_cache_size, @@ -70,6 +71,7 @@ extract_component_validation_rules, check_for_duplicate_components, get_json_schema_log_file_path, + export_graph ) @@ -1023,6 +1025,42 @@ def test_get_label_from_display_name(self, test_dn: str, data_model_labels: str) else: return return + +class TestExportGraph: + def test_export_graph_success(self, tmp_path): + # Create a temporary file path + file_path = tmp_path / "graph.pickle" + + # Define a sample schema + schema = {"node1": {"edges": ["node2", "node3"]}, "node2": {"edges": []}, "node3": {"edges": []}} + + # Call the export_graph function + export_graph(schema, str(file_path)) + + # Check if the file exists + assert file_path.exists() + + # Load the saved schema from the file + with open(file_path, "rb") as file: + saved_schema = pickle.load(file) + + # Check if the saved schema is equal to the original schema + assert saved_schema == schema + + def test_export_graph_failure(self, tmp_path, caplog): + + # Create a temporary file path + file_path = tmp_path / "graph.pickle" + + # Define a sample schema + schema = {"node1": {"edges": ["node2", "node3"]}, "node2": {"edges": []}, "node3": {"edges": []}} + + # Set the file path to a non-existent directory + invalid_file_path = str(tmp_path / "non_existent_directory" / "graph.pickle") + + # Call the export_graph function with an invalid file path + with pytest.raises(Exception): + export_graph(schema, invalid_file_path) @pytest.mark.parametrize( "data_model", From c2a06f631be2d3d057d8c7d15dee5700e81a06f5 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 11:05:10 -0700 Subject: [PATCH 079/124] run black --- tests/test_utils.py | 97 +++++++++++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 39 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 425312c53..216fcf2f7 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -71,7 +71,7 @@ extract_component_validation_rules, check_for_duplicate_components, get_json_schema_log_file_path, - export_graph + export_graph, ) @@ -198,7 +198,8 @@ (1073741825, 1073741824, 1181116006.4), ] -def get_metadataModel(helpers, model_name:str): + +def get_metadataModel(helpers, model_name: str): metadataModel = MetadataModel( inputMModelLocation=helpers.get_data_path(model_name), inputMModelLocationType="local", @@ -1025,14 +1026,19 @@ def test_get_label_from_display_name(self, test_dn: str, data_model_labels: str) else: return return - + + class TestExportGraph: def test_export_graph_success(self, tmp_path): # Create a temporary file path file_path = tmp_path / "graph.pickle" # Define a sample schema - schema = {"node1": {"edges": ["node2", "node3"]}, "node2": {"edges": []}, "node3": {"edges": []}} + schema = { + "node1": {"edges": ["node2", "node3"]}, + "node2": {"edges": []}, + "node3": {"edges": []}, + } # Call the export_graph function export_graph(schema, str(file_path)) @@ -1048,12 +1054,15 @@ def test_export_graph_success(self, tmp_path): assert saved_schema == schema def test_export_graph_failure(self, tmp_path, caplog): - # Create a temporary file path file_path = tmp_path / "graph.pickle" # Define a sample schema - schema = {"node1": {"edges": ["node2", "node3"]}, "node2": {"edges": []}, "node3": {"edges": []}} + schema = { + "node1": {"edges": ["node2", "node3"]}, + "node2": {"edges": []}, + "node3": {"edges": []}, + } # Set the file path to a non-existent directory invalid_file_path = str(tmp_path / "non_existent_directory" / "graph.pickle") @@ -1063,26 +1072,27 @@ def test_export_graph_failure(self, tmp_path, caplog): export_graph(schema, invalid_file_path) @pytest.mark.parametrize( - "data_model", - list(DATA_MODEL_DICT.keys()), - ids=list(DATA_MODEL_DICT.values()) + "data_model", list(DATA_MODEL_DICT.keys()), ids=list(DATA_MODEL_DICT.values()) ) @pytest.mark.parametrize( "source_node", ["Biospecimen", "Patient"], ids=["biospecimen_source", "patient_source"], ) - def test_get_json_schema_log_file_path(self, helpers, data_model:str, source_node: str): + def test_get_json_schema_log_file_path( + self, helpers, data_model: str, source_node: str + ): data_model_path = helpers.get_data_path(path=data_model) json_schema_log_file_path = get_json_schema_log_file_path( - data_model_path=data_model_path, - source_node=source_node) + data_model_path=data_model_path, source_node=source_node + ) # Check that model is not included in the json_schema_log_file_path - assert '.model' not in "data_model" + assert ".model" not in "data_model" # Check the file suffixs are what is expected. - assert ['schema', 'json'] == json_schema_log_file_path.split('.')[-2:] + assert ["schema", "json"] == json_schema_log_file_path.split(".")[-2:] + class TestValidateUtils: def test_validate_schema(self, helpers): @@ -1136,13 +1146,22 @@ def test_validate_property_schema(self, helpers): @pytest.mark.parametrize( ("manifest", "model", "root_node"), - [("mock_manifests/Patient_test_no_entry_for_cond_required_column.manifest.csv", - "example.model.csv", "Patient"), - ("mock_manifests/Valid_Test_Manifest_with_nones.csv", - "example_test_nones.model.csv", "MockComponent")] - ) + [ + ( + "mock_manifests/Patient_test_no_entry_for_cond_required_column.manifest.csv", + "example.model.csv", + "Patient", + ), + ( + "mock_manifests/Valid_Test_Manifest_with_nones.csv", + "example_test_nones.model.csv", + "MockComponent", + ), + ], + ) def test_convert_nan_entries_to_empty_strings( - self, helpers, manifest, model, root_node): + self, helpers, manifest, model, root_node + ): # Get manifest and data model path manifest_path = helpers.get_data_path(manifest) model_path = helpers.get_data_path(model) @@ -1166,37 +1185,37 @@ def test_convert_nan_entries_to_empty_strings( manifest_path, preserve_raw_input=False, allow_na_values=True, - **load_args,) + **load_args, + ) metadataModel = get_metadataModel(helpers, model) # Instantiate Validate manifest, and run manifest validation - # In this step the manifest is modified while running rule + # In this step the manifest is modified while running rule # validation so need to do this step to get the updated manfest. - vm = ValidateManifest( - errors, manifest, manifest_path, dmge, json_schema) + vm = ValidateManifest(errors, manifest, manifest_path, dmge, json_schema) manifest, vmr_errors, vmr_warnings = vm.validate_manifest_rules( - manifest, dmge, restrict_rules=False, project_scope=["syn54126707"], + manifest, + dmge, + restrict_rules=False, + project_scope=["syn54126707"], ) # Run convert nan function - output = validate_utils.convert_nan_entries_to_empty_strings( - manifest=manifest - ) + output = validate_utils.convert_nan_entries_to_empty_strings(manifest=manifest) # Compare post rule validation manifest with output manifest looking # for expected nan to empty string conversion - if root_node == 'Patient': - assert manifest['Family History'][0] == [''] - assert output['Family History'][0] == [''] - elif root_node == 'MockComponent': - assert manifest['Check List'][2] == [''] - assert manifest['Check List Like Enum'][2] == [] - assert type(manifest['Check NA'][2]) == type(pd.NA) - - assert output['Check List'][2] == [''] - assert output['Check List Like Enum'][2] == [] - + if root_node == "Patient": + assert manifest["Family History"][0] == [""] + assert output["Family History"][0] == [""] + elif root_node == "MockComponent": + assert manifest["Check List"][2] == [""] + assert manifest["Check List Like Enum"][2] == [] + assert type(manifest["Check NA"][2]) == type(pd.NA) + + assert output["Check List"][2] == [""] + assert output["Check List Like Enum"][2] == [] def test_get_list_robustness(self, helpers): return From 1e5bd7d803602b2ed8d0e879bc5f3d04823c5532 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 12:29:19 -0700 Subject: [PATCH 080/124] add graph_url spec to manifest/generate endpoint --- schematic_api/api/openapi/api.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/schematic_api/api/openapi/api.yaml b/schematic_api/api/openapi/api.yaml index 15a3540d1..f18321cee 100644 --- a/schematic_api/api/openapi/api.yaml +++ b/schematic_api/api/openapi/api.yaml @@ -110,6 +110,15 @@ paths: class_label, default, use standard class or property label. Do not change from default unless there is a real need, using 'display_label' can have consequences if not used properly. required: false + - in: query + name: graph_url + schema: + type: string + nullable: true + description: Graph Pickle URL + example: >- + url_to_graph_pickle_in_github + required: false operationId: schematic_api.api.routes.get_manifest_route responses: "200": From c849f92a1d4c55a0dc35893280a03bee0e593197 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 12:29:57 -0700 Subject: [PATCH 081/124] add function to download temp pickle file from url. Add data_model_pickle parameter to manifest/generate --- schematic_api/api/routes.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/schematic_api/api/routes.py b/schematic_api/api/routes.py index 59a6cd55e..2cf57c7b9 100644 --- a/schematic_api/api/routes.py +++ b/schematic_api/api/routes.py @@ -311,6 +311,11 @@ def get_temp_csv(schema_url): # get path to temporary csv file return tmp_file.name +def get_temp_pickle(graph_url): + # retrieve a pickle via URL and store it in a temporary location + with urllib.request.urlopen(graph_url) as response: + with tempfile.NamedTemporaryFile(delete=False, suffix=".pickle") as tmp_file: + shutil.copyfileobj(response, tmp_file) def get_temp_model_path(schema_url): # Get model type: @@ -319,9 +324,11 @@ def get_temp_model_path(schema_url): temp_path = get_temp_csv(schema_url) elif model_extension == "JSONLD": temp_path = get_temp_jsonld(schema_url) + elif model_extension == "PICKLE": + temp_path = get_temp_pickle(schema_url) else: raise ValueError( - "Did not provide a valid model type CSV or JSONLD, please check submission and try again." + "Did not provide a valid model type CSV or JSONLD or PICKLE, please check submission and try again." ) return temp_path @@ -338,6 +345,7 @@ def get_manifest_route( strict_validation: bool = True, data_model_labels: DisplayLabelType = "class_label", data_type: str = None, + graph_url: str = None, ): """Get the immediate dependencies that are related to a given source node. Args: @@ -349,6 +357,7 @@ def get_manifest_route( use_annotations: Whether to use existing annotations during manifest generation asset_view: ID of view listing all project data assets. For example, for Synapse this would be the Synapse ID of the fileview listing all data assets for a given project. strict: bool, strictness with which to apply validation rules to google sheets. + graph_url: str, URL to a pickled graph object. Returns: Googlesheet URL (if sheet_url is True), or pandas dataframe (if sheet_url is False). """ @@ -367,6 +376,7 @@ def get_manifest_route( strict=strict_validation, use_annotations=use_annotations, data_model_labels=data_model_labels, + data_model_pickle=graph_url ) # return an excel file if output_format is set to "excel" From 8041b07a21b8f93de6cd8e8d47eef17de37e36f9 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 12:40:40 -0700 Subject: [PATCH 082/124] use data_model_graph_pickle argument in manifest/generate endpoint --- schematic_api/api/routes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematic_api/api/routes.py b/schematic_api/api/routes.py index 2cf57c7b9..f7cffedbe 100644 --- a/schematic_api/api/routes.py +++ b/schematic_api/api/routes.py @@ -376,7 +376,7 @@ def get_manifest_route( strict=strict_validation, use_annotations=use_annotations, data_model_labels=data_model_labels, - data_model_pickle=graph_url + data_model_graph_pickle=graph_url ) # return an excel file if output_format is set to "excel" From 0870fa1a1f0cdf00af34a35f845265eb209c8392 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 12:44:49 -0700 Subject: [PATCH 083/124] download temp pickle in manifest/generate endpoint --- schematic_api/api/routes.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/schematic_api/api/routes.py b/schematic_api/api/routes.py index f7cffedbe..fb6a24792 100644 --- a/schematic_api/api/routes.py +++ b/schematic_api/api/routes.py @@ -366,6 +366,9 @@ def get_manifest_route( config_handler(asset_view=asset_view) + if graph_url is not None: + graph_url = get_temp_model_path(graph_url) + all_results = ManifestGenerator.create_manifests( path_to_data_model=schema_url, output_format=output_format, From 680275350578e88743ea0afe2e1e2591c91bad01 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 13:37:54 -0700 Subject: [PATCH 084/124] check that files are created in schema convert --- tests/test_cli.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/test_cli.py b/tests/test_cli.py index 6aca1535f..dcfc51ea4 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -66,18 +66,24 @@ def test_schema_convert_cli(self, runner, output_path, output_type): resultOne = runner.invoke(schema, ["convert", model]) assert resultOne.exit_code == expected + # check output_path file is created then remove it + assert os.path.exists(output_path) resultTwo = runner.invoke( schema, ["convert", model, "--output_path", output_path] ) assert resultTwo.exit_code == expected + # check output_path file is created then remove it + assert os.path.exists(output_path) resultThree = runner.invoke( schema, ["convert", model, "--output_type", output_type] ) assert resultThree.exit_code == expected + # check output_path file is created then remove it + assert os.path.exists(output_path) resultFour = runner.invoke( schema, @@ -92,6 +98,8 @@ def test_schema_convert_cli(self, runner, output_path, output_type): ) assert resultFour.exit_code == expected + # check output_path file is created then remove it + assert os.path.exists(output_path) result = runner.invoke( schema, @@ -106,6 +114,8 @@ def test_schema_convert_cli(self, runner, output_path, output_type): ) assert result.exit_code == expected + # check output_path file is created then remove it + assert os.path.exists(output_path) resultFive = runner.invoke( schema, @@ -120,12 +130,16 @@ def test_schema_convert_cli(self, runner, output_path, output_type): ) assert resultFive.exit_code == expected + # check output_path file is created then remove it + assert os.path.exists(output_path) resultSix = runner.invoke( schema, ["convert", model, "--output_jsonld", "", "--output_path", ""] ) assert resultSix.exit_code == expected + # check output_path file is created then remove it + assert os.path.exists(output_path) # get manifest by default # by default this should download the manifest as a CSV file From 23b7e1d6010c3958548edbca8f3eba62d8d2ffa8 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 13:41:51 -0700 Subject: [PATCH 085/124] update docstring and use if ... is not None instead of if not ... --- schematic/manifest/generator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/schematic/manifest/generator.py b/schematic/manifest/generator.py index 23a668876..e7efa8915 100644 --- a/schematic/manifest/generator.py +++ b/schematic/manifest/generator.py @@ -1650,7 +1650,7 @@ def create_manifests( Args: path_to_data_model (str): str path to data model - data_model_graph_pickle (str): A data model graph as csv or pickle + data_model_graph_pickle (str): path to pickled networkx MultiDiGraph object graph_data_model (str): An networkx MultiDiGraph object data_types (list): a list of data types access_token (str, optional): synapse access token. Required when getting an existing manifest. Defaults to None. @@ -1682,7 +1682,7 @@ def create_manifests( "Please check your submission and try again." ) - if not graph_data_model: + if graph_data_model is not None: if data_model_graph_pickle: """What if pickle file does not fit in memory?""" graph_data_model = read_pickle(data_model_graph_pickle) From fa5e30812ddca7086633386f9838b8161d18df7c Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 27 Aug 2024 14:00:25 -0700 Subject: [PATCH 086/124] use if ... is None instead of if ... is not None --- schematic/manifest/generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematic/manifest/generator.py b/schematic/manifest/generator.py index e7efa8915..cf1c1a241 100644 --- a/schematic/manifest/generator.py +++ b/schematic/manifest/generator.py @@ -1682,7 +1682,7 @@ def create_manifests( "Please check your submission and try again." ) - if graph_data_model is not None: + if graph_data_model is None: if data_model_graph_pickle: """What if pickle file does not fit in memory?""" graph_data_model = read_pickle(data_model_graph_pickle) From afbe448158596e8f035a80b5098ce65eab8496d1 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 28 Aug 2024 09:27:15 -0700 Subject: [PATCH 087/124] add graph_url to validate and submission endpoints --- schematic_api/api/openapi/api.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/schematic_api/api/openapi/api.yaml b/schematic_api/api/openapi/api.yaml index f18321cee..a915e3c63 100644 --- a/schematic_api/api/openapi/api.yaml +++ b/schematic_api/api/openapi/api.yaml @@ -312,6 +312,15 @@ paths: description: List, a subset of the projects contained within the asset view that are relevant for the current operation. Speeds up some operations that interact with Synapse. Relevant for validating manifests involving cross-manifest validation, but optional. example: ['syn23643250', 'syn47218127', 'syn47218347'] required: false + - in: query + name: graph_url + schema: + type: string + nullable: true + description: Graph Pickle URL + example: >- + url_to_graph_pickle_in_github + required: false operationId: schematic_api.api.routes.validate_manifest_route responses: @@ -468,6 +477,15 @@ paths: description: List, a subset of the projects contained within the asset view that are relevant for the current operation. Speeds up some operations that interact with Synapse. example: ['syn23643250', 'syn47218127', 'syn47218347'] required: false + - in: query + name: graph_url + schema: + type: string + nullable: true + description: Graph Pickle URL + example: >- + url_to_graph_pickle_in_github + required: false operationId: schematic_api.api.routes.submit_manifest_route responses: "200": From e4d0b7c652862688622223088cedbfa923beefb5 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 28 Aug 2024 09:27:34 -0700 Subject: [PATCH 088/124] add graph_url to validate and submission endpoints --- schematic_api/api/routes.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/schematic_api/api/routes.py b/schematic_api/api/routes.py index fb6a24792..5fc741715 100644 --- a/schematic_api/api/routes.py +++ b/schematic_api/api/routes.py @@ -412,6 +412,7 @@ def validate_manifest_route( json_str=None, asset_view=None, project_scope=None, + graph_url=None, ): # Access token now stored in request header access_token = get_access_token() @@ -439,6 +440,8 @@ def validate_manifest_route( # get path to temp data model file (csv or jsonld) as appropriate data_model = get_temp_model_path(schema_url) + if graph_url is not None: + graph_url = get_temp_model_path(graph_url) metadata_model = MetadataModel( inputMModelLocation=data_model, @@ -452,6 +455,7 @@ def validate_manifest_route( restrict_rules=restrict_rules, project_scope=project_scope, access_token=access_token, + data_model_graph_pickle=graph_url ) res_dict = {"errors": errors, "warnings": warnings} @@ -474,6 +478,7 @@ def submit_manifest_route( table_column_names=None, annotation_keys=None, file_annotations_upload: bool = True, + graph_url=None, ): # call config_handler() config_handler(asset_view=asset_view) @@ -506,6 +511,8 @@ def submit_manifest_route( # get path to temp data model file (csv or jsonld) as appropriate data_model = get_temp_model_path(schema_url) + if graph_url is not None: + graph_url = get_temp_model_path(graph_url) if not table_column_names: table_column_names = "class_label" @@ -531,6 +538,7 @@ def submit_manifest_route( table_column_names=table_column_names, annotation_keys=annotation_keys, file_annotations_upload=file_annotations_upload, + data_model_graph_pickle=graph_url ) return manifest_id From a7d7366f974cf508813eb9530f4c90404062f2f5 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 28 Aug 2024 10:28:16 -0700 Subject: [PATCH 089/124] add pickled htan data model for testing --- tests/data/htan.model.pickle | Bin 0 -> 1306981 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/data/htan.model.pickle diff --git a/tests/data/htan.model.pickle b/tests/data/htan.model.pickle new file mode 100644 index 0000000000000000000000000000000000000000..c58efd0254e1c8326024730a97002186f5895a6b GIT binary patch literal 1306981 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

  • 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

    %N*Yn~AjWY0K(-&sAq2QN5*2 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

    k-V9}k4eo!Fg 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
    D~cv4g-$Ix8u51Xw9&rNoW_EA6bb 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 Date: Wed, 28 Aug 2024 13:21:04 -0700 Subject: [PATCH 090/124] remove data model graph parameter from validation and submission. It's only available for manifest generation. Also rework some logic with reading the graph pickle --- schematic_api/api/routes.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/schematic_api/api/routes.py b/schematic_api/api/routes.py index 5fc741715..cf40e265e 100644 --- a/schematic_api/api/routes.py +++ b/schematic_api/api/routes.py @@ -37,6 +37,7 @@ DisplayLabelType, get_property_label_from_display_name, ) +from schematic.utils.io_utils import read_pickle from schematic.visualization.attributes_explorer import AttributesExplorer from schematic.visualization.tangled_tree import TangledTree @@ -317,6 +318,8 @@ def get_temp_pickle(graph_url): with tempfile.NamedTemporaryFile(delete=False, suffix=".pickle") as tmp_file: shutil.copyfileobj(response, tmp_file) + return tmp_file.name + def get_temp_model_path(schema_url): # Get model type: model_extension = pathlib.Path(schema_url).suffix.replace(".", "").upper() @@ -367,7 +370,8 @@ def get_manifest_route( config_handler(asset_view=asset_view) if graph_url is not None: - graph_url = get_temp_model_path(graph_url) + graph_path = get_temp_model_path(graph_url) + graph_data_model=read_pickle(graph_path) all_results = ManifestGenerator.create_manifests( path_to_data_model=schema_url, @@ -379,7 +383,7 @@ def get_manifest_route( strict=strict_validation, use_annotations=use_annotations, data_model_labels=data_model_labels, - data_model_graph_pickle=graph_url + graph_data_model=graph_data_model ) # return an excel file if output_format is set to "excel" @@ -412,7 +416,6 @@ def validate_manifest_route( json_str=None, asset_view=None, project_scope=None, - graph_url=None, ): # Access token now stored in request header access_token = get_access_token() @@ -440,8 +443,6 @@ def validate_manifest_route( # get path to temp data model file (csv or jsonld) as appropriate data_model = get_temp_model_path(schema_url) - if graph_url is not None: - graph_url = get_temp_model_path(graph_url) metadata_model = MetadataModel( inputMModelLocation=data_model, @@ -455,7 +456,6 @@ def validate_manifest_route( restrict_rules=restrict_rules, project_scope=project_scope, access_token=access_token, - data_model_graph_pickle=graph_url ) res_dict = {"errors": errors, "warnings": warnings} @@ -478,7 +478,6 @@ def submit_manifest_route( table_column_names=None, annotation_keys=None, file_annotations_upload: bool = True, - graph_url=None, ): # call config_handler() config_handler(asset_view=asset_view) @@ -511,8 +510,6 @@ def submit_manifest_route( # get path to temp data model file (csv or jsonld) as appropriate data_model = get_temp_model_path(schema_url) - if graph_url is not None: - graph_url = get_temp_model_path(graph_url) if not table_column_names: table_column_names = "class_label" @@ -538,7 +535,6 @@ def submit_manifest_route( table_column_names=table_column_names, annotation_keys=annotation_keys, file_annotations_upload=file_annotations_upload, - data_model_graph_pickle=graph_url ) return manifest_id From cec7aa6f6df0476d54cd70f2ee4a1fe21a2867e3 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 28 Aug 2024 13:21:31 -0700 Subject: [PATCH 091/124] remove graph_url from validation and submission endpoints --- schematic_api/api/openapi/api.yaml | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/schematic_api/api/openapi/api.yaml b/schematic_api/api/openapi/api.yaml index a915e3c63..f18321cee 100644 --- a/schematic_api/api/openapi/api.yaml +++ b/schematic_api/api/openapi/api.yaml @@ -312,15 +312,6 @@ paths: description: List, a subset of the projects contained within the asset view that are relevant for the current operation. Speeds up some operations that interact with Synapse. Relevant for validating manifests involving cross-manifest validation, but optional. example: ['syn23643250', 'syn47218127', 'syn47218347'] required: false - - in: query - name: graph_url - schema: - type: string - nullable: true - description: Graph Pickle URL - example: >- - url_to_graph_pickle_in_github - required: false operationId: schematic_api.api.routes.validate_manifest_route responses: @@ -477,15 +468,6 @@ paths: description: List, a subset of the projects contained within the asset view that are relevant for the current operation. Speeds up some operations that interact with Synapse. example: ['syn23643250', 'syn47218127', 'syn47218347'] required: false - - in: query - name: graph_url - schema: - type: string - nullable: true - description: Graph Pickle URL - example: >- - url_to_graph_pickle_in_github - required: false operationId: schematic_api.api.routes.submit_manifest_route responses: "200": From b52bfdcffc13136e4792c8f3cc7488d5510649ff Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 28 Aug 2024 13:36:42 -0700 Subject: [PATCH 092/124] run black on routes.py --- schematic_api/api/routes.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/schematic_api/api/routes.py b/schematic_api/api/routes.py index cf40e265e..be4e5e235 100644 --- a/schematic_api/api/routes.py +++ b/schematic_api/api/routes.py @@ -312,6 +312,7 @@ def get_temp_csv(schema_url): # get path to temporary csv file return tmp_file.name + def get_temp_pickle(graph_url): # retrieve a pickle via URL and store it in a temporary location with urllib.request.urlopen(graph_url) as response: @@ -320,6 +321,7 @@ def get_temp_pickle(graph_url): return tmp_file.name + def get_temp_model_path(schema_url): # Get model type: model_extension = pathlib.Path(schema_url).suffix.replace(".", "").upper() @@ -371,7 +373,7 @@ def get_manifest_route( if graph_url is not None: graph_path = get_temp_model_path(graph_url) - graph_data_model=read_pickle(graph_path) + graph_data_model = read_pickle(graph_path) all_results = ManifestGenerator.create_manifests( path_to_data_model=schema_url, @@ -383,7 +385,7 @@ def get_manifest_route( strict=strict_validation, use_annotations=use_annotations, data_model_labels=data_model_labels, - graph_data_model=graph_data_model + graph_data_model=graph_data_model, ) # return an excel file if output_format is set to "excel" From 8a64c398ccf8b8adc854a4e273c89edeb316fd0f Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 28 Aug 2024 13:44:31 -0700 Subject: [PATCH 093/124] set graph_data_model to None before looking for graph_url --- schematic_api/api/routes.py | 1 + 1 file changed, 1 insertion(+) diff --git a/schematic_api/api/routes.py b/schematic_api/api/routes.py index be4e5e235..5524bfc09 100644 --- a/schematic_api/api/routes.py +++ b/schematic_api/api/routes.py @@ -371,6 +371,7 @@ def get_manifest_route( config_handler(asset_view=asset_view) + graph_data_model = None if graph_url is not None: graph_path = get_temp_model_path(graph_url) graph_data_model = read_pickle(graph_path) From 5bd3fc00d31884c4c8cd8414fad23bab5031af34 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 28 Aug 2024 13:47:23 -0700 Subject: [PATCH 094/124] add DataModelParser back to tangled_tree.py --- schematic/visualization/tangled_tree.py | 1 + 1 file changed, 1 insertion(+) diff --git a/schematic/visualization/tangled_tree.py b/schematic/visualization/tangled_tree.py index 0d7dfc927..5686a0a46 100644 --- a/schematic/visualization/tangled_tree.py +++ b/schematic/visualization/tangled_tree.py @@ -16,6 +16,7 @@ from networkx.classes.reportviews import EdgeDataView, NodeView # type: ignore from typing_extensions import assert_never +from schematic.schemas.data_model_parser import DataModelParser from schematic.schemas.data_model_graph import DataModelGraph, DataModelGraphExplorer from schematic.utils.io_utils import load_json, read_pickle from schematic.utils.schema_utils import DisplayLabelType From 9c2eddeee7a08cd23c5b51ea241f74898500d72e Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 09:22:08 -0700 Subject: [PATCH 095/124] change logger.info to click.echo --- schematic/schemas/commands.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index 8250ff247..62e003bdf 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -92,7 +92,7 @@ def convert( data_model_parser = DataModelParser(schema) # Parse Model - logger.info("Parsing data model.") + click.echo("Parsing data model.") parsed_data_model = data_model_parser.parse_model() # Convert parsed model to graph @@ -100,11 +100,11 @@ def convert( data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) # Generate graphschema - logger.info("Generating data model graph.") + click.echo("Generating data model graph.") graph_data_model = data_model_grapher.graph # Validate generated data model. - logger.info("Validating the data model internally.") + click.echo("Validating the data model internally.") data_model_validator = DataModelValidator(graph=graph_data_model) data_model_errors, data_model_warnings = data_model_validator.run_checks() @@ -134,21 +134,21 @@ def convert( else: output_file_no_ext = re.sub("[.](jsonld|csv|pickle)$", "", output_jsonld) - logger.info( + click.echo( "By default, the JSON-LD output will be stored alongside the first " f"input CSV or JSON-LD file. In this case, it will appear here: '{output_jsonld}'. " "You can use the `--output_jsonld` argument to specify another file path." ) if output_type in ["graph", "all"]: - logger.info("Export graph to pickle.") + click.echo("Export graph to pickle.") output_graph = output_file_no_ext + ".pickle" export_graph(graph_data_model, output_graph) if output_type == "graph": click.echo(f"Graph created {output_graph}") return 0 - logger.info("Converting data model to JSON-LD") + click.echo("Converting data model to JSON-LD") jsonld_data_model = convert_graph_to_jsonld(graph=graph_data_model) # output JSON-LD file alongside CSV file by default, get path. @@ -157,7 +157,7 @@ def convert( # saving updated schema.org schema try: export_schema(jsonld_data_model, output_jsonld) - logger.info( + click.echo( f"The Data Model was created and saved to '{output_jsonld}' location." ) except: # pylint: disable=bare-except From 58c14292d5d554d1074133d24582a3fab4eeb981 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 09:27:43 -0700 Subject: [PATCH 096/124] Check if pickle file contains a networkx MultiDiGraph object --- schematic/visualization/attributes_explorer.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/schematic/visualization/attributes_explorer.py b/schematic/visualization/attributes_explorer.py index abc5a0e2b..cfd5674f3 100644 --- a/schematic/visualization/attributes_explorer.py +++ b/schematic/visualization/attributes_explorer.py @@ -36,7 +36,12 @@ def __init__( if graph_data_model is not None: self.graph_data_model = graph_data_model elif data_model_graph_pickle is not None: - self.graph_data_model = read_pickle(data_model_graph_pickle) + data_model_graph = read_pickle(data_model_graph_pickle) + if not isinstance(data_model_graph, nx.MultiDiGraph): + raise ValueError( + "The data model graph must be a networkx MultiDiGraph object." + ) + self.graph_data_model = data_model_graph # Parse Model if parsed_data_model is None: From 487e31d8848b14c7cfa63d646d5614ee2b80bf2d Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 09:32:36 -0700 Subject: [PATCH 097/124] explain options to schema convert output_type --- schematic/help.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/schematic/help.py b/schematic/help.py index 20117e1c1..173c26d3f 100644 --- a/schematic/help.py +++ b/schematic/help.py @@ -216,7 +216,13 @@ "output_jsonld": ( "Path to where the generated JSON-LD file needs to be outputted." ), - "output_type": ("Output format to export the schema."), + "output_type": ( + "Output format to export the schema. " + "Options are 'jsonld', 'graph', 'all'. Default is 'jsonld'." + "'jsonld' will output the schema as a JSON-LD file. " + "'graph' will output an nx graph object of the schema as a pickle file." + "'all' will output both the JSON-LD file and the graph object." + ), "data_model_labels": DATA_MODEL_LABELS_HELP, } } From e13f693fcbe88e66bbdb8a9dce3783af476ca35a Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 09:34:38 -0700 Subject: [PATCH 098/124] update data_model_graph_pickle docstring for ManifestGenerator --- schematic/manifest/generator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/schematic/manifest/generator.py b/schematic/manifest/generator.py index cf1c1a241..0f8de9ff7 100644 --- a/schematic/manifest/generator.py +++ b/schematic/manifest/generator.py @@ -1650,8 +1650,8 @@ def create_manifests( Args: path_to_data_model (str): str path to data model - data_model_graph_pickle (str): path to pickled networkx MultiDiGraph object - graph_data_model (str): An networkx MultiDiGraph object + data_model_graph_pickle (str, optional): path to pickled networkx MultiDiGraph object. Defaults to None. + graph_data_model (str, optional): An networkx MultiDiGraph object. Defaults to None. data_types (list): a list of data types access_token (str, optional): synapse access token. Required when getting an existing manifest. Defaults to None. dataset_ids (list, optional): a list of dataset ids when generating an existing manifest. Defaults to None. From 3d5da4058cb525f40d0287016acf90469b8d2b79 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 09:44:17 -0700 Subject: [PATCH 099/124] don't return 0 at the end of schema convert --- schematic/schemas/commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index 62e003bdf..ce4b883b0 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -172,4 +172,4 @@ def convert( # get the execution time elapsed_time = time.strftime("%M:%S", time.gmtime(end_time - start_time)) click.echo(f"Execution time: {elapsed_time} (M:S)") - return 0 + return From a331725ea0c11b26766a8f612c1e12c678e8d202 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 09:47:56 -0700 Subject: [PATCH 100/124] raise a valueError instead of logger.error for passing a bad filepath to schema convert --- schematic/schemas/commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index ce4b883b0..9b1b23c61 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -161,7 +161,7 @@ def convert( f"The Data Model was created and saved to '{output_jsonld}' location." ) except: # pylint: disable=bare-except - logger.error( + raise ValueError( f"The Data Model could not be created by using '{output_jsonld}' location. " "Please check your file path again" ) From 3ed11774a491bedcc861956a564d79856f297a73 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 09:54:32 -0700 Subject: [PATCH 101/124] return 0 at the end of schema convert to avoid error 'error: Return value expected [return-value]' --- schematic/schemas/commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index 9b1b23c61..31b523dd9 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -172,4 +172,4 @@ def convert( # get the execution time elapsed_time = time.strftime("%M:%S", time.gmtime(end_time - start_time)) click.echo(f"Execution time: {elapsed_time} (M:S)") - return + return 0 From b6728d349268452dd7a438163fb97f8e5e7959ce Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 10:01:16 -0700 Subject: [PATCH 102/124] Raise an actual exception and valueError for bad filepath to schema convert --- schematic/schemas/commands.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index 31b523dd9..20a43d37a 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -160,11 +160,11 @@ def convert( click.echo( f"The Data Model was created and saved to '{output_jsonld}' location." ) - except: # pylint: disable=bare-except + except Exception as exc: raise ValueError( f"The Data Model could not be created by using '{output_jsonld}' location. " "Please check your file path again" - ) + ) from exc # get the end time end_time = time.time() From b7460eabdd98f6b6fa5b543845152064c7b26161 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 10:16:53 -0700 Subject: [PATCH 103/124] add more information to schema convert when saving the graph as a pickle. --- schematic/utils/schema_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematic/utils/schema_utils.py b/schematic/utils/schema_utils.py index a0b260835..88bf50f65 100644 --- a/schematic/utils/schema_utils.py +++ b/schematic/utils/schema_utils.py @@ -512,7 +512,7 @@ def export_graph(schema: dict, file_path: str) -> None: try: with open(file_path, "wb") as file: pickle.dump(schema, file) - logger.info(f"The graph was created and saved to '{file_path}'.") + logger.info(f"The data model graph was created and saved to a pickle file located at: '{file_path}'.") except SystemExit as error: logger.exception( f"The graph failed to save to '{file_path}'. Please check your file path again." From 53e639b693c40cbd58ac3325df961abb36371b56 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 10:20:19 -0700 Subject: [PATCH 104/124] add argument and return types to get_temp_pickle --- schematic_api/api/routes.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/schematic_api/api/routes.py b/schematic_api/api/routes.py index 5524bfc09..1a83f15ac 100644 --- a/schematic_api/api/routes.py +++ b/schematic_api/api/routes.py @@ -313,7 +313,9 @@ def get_temp_csv(schema_url): return tmp_file.name -def get_temp_pickle(graph_url): +def get_temp_pickle( + graph_url: str +) -> str: # retrieve a pickle via URL and store it in a temporary location with urllib.request.urlopen(graph_url) as response: with tempfile.NamedTemporaryFile(delete=False, suffix=".pickle") as tmp_file: From 498851b3e4606fe4303de2fcedeadd98ecbc97a6 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 10:24:02 -0700 Subject: [PATCH 105/124] run the black code formatter --- schematic/utils/schema_utils.py | 4 +++- schematic_api/api/routes.py | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/schematic/utils/schema_utils.py b/schematic/utils/schema_utils.py index 88bf50f65..9b3c510c9 100644 --- a/schematic/utils/schema_utils.py +++ b/schematic/utils/schema_utils.py @@ -512,7 +512,9 @@ def export_graph(schema: dict, file_path: str) -> None: try: with open(file_path, "wb") as file: pickle.dump(schema, file) - logger.info(f"The data model graph was created and saved to a pickle file located at: '{file_path}'.") + logger.info( + f"The data model graph was created and saved to a pickle file located at: '{file_path}'." + ) except SystemExit as error: logger.exception( f"The graph failed to save to '{file_path}'. Please check your file path again." diff --git a/schematic_api/api/routes.py b/schematic_api/api/routes.py index 1a83f15ac..3803f85fe 100644 --- a/schematic_api/api/routes.py +++ b/schematic_api/api/routes.py @@ -313,9 +313,7 @@ def get_temp_csv(schema_url): return tmp_file.name -def get_temp_pickle( - graph_url: str -) -> str: +def get_temp_pickle(graph_url: str) -> str: # retrieve a pickle via URL and store it in a temporary location with urllib.request.urlopen(graph_url) as response: with tempfile.NamedTemporaryFile(delete=False, suffix=".pickle") as tmp_file: From 58aef406293fa401f2801f0032de576f0415eb74 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 10:30:29 -0700 Subject: [PATCH 106/124] turn a single line that pylint states is too long into two shorter lines of satisfactory length --- schematic/utils/schema_utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/schematic/utils/schema_utils.py b/schematic/utils/schema_utils.py index 9b3c510c9..fe9aeaec7 100644 --- a/schematic/utils/schema_utils.py +++ b/schematic/utils/schema_utils.py @@ -513,7 +513,8 @@ def export_graph(schema: dict, file_path: str) -> None: with open(file_path, "wb") as file: pickle.dump(schema, file) logger.info( - f"The data model graph was created and saved to a pickle file located at: '{file_path}'." + f"The data model graph was created and saved " + "to a pickle file located at: '{file_path}'." ) except SystemExit as error: logger.exception( From 03f7497284545076f1c581917e96b0bcf953f9a3 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 10:35:22 -0700 Subject: [PATCH 107/124] swap the f in logger.echo to avoid 'Using an f-string that does not have any interpolated variables' --- schematic/utils/schema_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/schematic/utils/schema_utils.py b/schematic/utils/schema_utils.py index fe9aeaec7..2523bb332 100644 --- a/schematic/utils/schema_utils.py +++ b/schematic/utils/schema_utils.py @@ -513,8 +513,8 @@ def export_graph(schema: dict, file_path: str) -> None: with open(file_path, "wb") as file: pickle.dump(schema, file) logger.info( - f"The data model graph was created and saved " - "to a pickle file located at: '{file_path}'." + "The data model graph was created and saved " + f"to a pickle file located at: '{file_path}'." ) except SystemExit as error: logger.exception( From 2a7ea55d082471dfe83915582a22b725926899a1 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 14:33:44 -0700 Subject: [PATCH 108/124] message where graph is saved in schema convert cli --- schematic/schemas/commands.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/schematic/schemas/commands.py b/schematic/schemas/commands.py index 20a43d37a..84d4557ec 100644 --- a/schematic/schemas/commands.py +++ b/schematic/schemas/commands.py @@ -141,11 +141,10 @@ def convert( ) if output_type in ["graph", "all"]: - click.echo("Export graph to pickle.") output_graph = output_file_no_ext + ".pickle" + click.echo(f"Saving data model graph to '{output_graph}'.") export_graph(graph_data_model, output_graph) if output_type == "graph": - click.echo(f"Graph created {output_graph}") return 0 click.echo("Converting data model to JSON-LD") From 275fbae9c92d3a3d26f1c312fe362359b6e8683a Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 14:36:41 -0700 Subject: [PATCH 109/124] check for FileNotFound error instead of generic exception --- tests/test_utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 8ac61360e..0d1cd5dde 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1069,7 +1069,8 @@ def test_export_graph_failure(self, tmp_path, caplog): invalid_file_path = str(tmp_path / "non_existent_directory" / "graph.pickle") # Call the export_graph function with an invalid file path - with pytest.raises(Exception): + # and catch the exception + with pytest.raises(FileNotFoundError): export_graph(schema, invalid_file_path) @pytest.mark.parametrize( From 89cd4ce3bef4ce34a1c1b14fb6672e66f37c1ed8 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 14:38:38 -0700 Subject: [PATCH 110/124] change test variables to camel case --- tests/test_cli.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index dcfc51ea4..06bd3adb0 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -63,29 +63,29 @@ def test_schema_convert_cli(self, runner, output_path, output_type): label_type = "class_label" expected = 0 - resultOne = runner.invoke(schema, ["convert", model]) + result_one = runner.invoke(schema, ["convert", model]) - assert resultOne.exit_code == expected + assert result_one.exit_code == expected # check output_path file is created then remove it assert os.path.exists(output_path) - resultTwo = runner.invoke( + result_two = runner.invoke( schema, ["convert", model, "--output_path", output_path] ) - assert resultTwo.exit_code == expected + assert result_two.exit_code == expected # check output_path file is created then remove it assert os.path.exists(output_path) - resultThree = runner.invoke( + result_three = runner.invoke( schema, ["convert", model, "--output_type", output_type] ) - assert resultThree.exit_code == expected + assert result_three.exit_code == expected # check output_path file is created then remove it assert os.path.exists(output_path) - resultFour = runner.invoke( + result_four = runner.invoke( schema, [ "convert", @@ -97,7 +97,7 @@ def test_schema_convert_cli(self, runner, output_path, output_type): ], ) - assert resultFour.exit_code == expected + assert result_four.exit_code == expected # check output_path file is created then remove it assert os.path.exists(output_path) @@ -117,7 +117,7 @@ def test_schema_convert_cli(self, runner, output_path, output_type): # check output_path file is created then remove it assert os.path.exists(output_path) - resultFive = runner.invoke( + result_five = runner.invoke( schema, [ "convert", @@ -129,15 +129,15 @@ def test_schema_convert_cli(self, runner, output_path, output_type): ], ) - assert resultFive.exit_code == expected + assert result_five.exit_code == expected # check output_path file is created then remove it assert os.path.exists(output_path) - resultSix = runner.invoke( + result_six = runner.invoke( schema, ["convert", model, "--output_jsonld", "", "--output_path", ""] ) - assert resultSix.exit_code == expected + assert result_six.exit_code == expected # check output_path file is created then remove it assert os.path.exists(output_path) From 3197abf76525981dddbbefde14fb229de7e8587f Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 15:09:12 -0700 Subject: [PATCH 111/124] document schema convert tests --- tests/test_cli.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 06bd3adb0..3f0c90f50 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -50,12 +50,22 @@ def assert_expected_file(self, result, output_path): @pytest.mark.parametrize( "output_path", - ["tests/data/example.model.pickle", "tests/data/example.model.jsonld"], + [ + # Test case 1: pickle file passed to output_path + "tests/data/example.model.pickle", + # Test case 2: jsonld file passed to output_path + "tests/data/example.model.jsonld"], ids=["output_path_pickle", "output_path_jsonld"], ) @pytest.mark.parametrize( "output_type", - ["jsonld", "graph", "all"], + [ + # Test case 1: jsonld passed to output_type + "jsonld", + # Test case 2: graph passed to output_type + "graph", + # Test case 3: both jsonld and graph are created + "all"], ids=["output_type_jsonld", "output_type_graph", "output_type_all"], ) def test_schema_convert_cli(self, runner, output_path, output_type): From abd1630f3b66899c50859c5ae4fcccd95e09e65c Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 15:14:34 -0700 Subject: [PATCH 112/124] turn get_temp_ functions into one single function --- schematic_api/api/routes.py | 46 ++++++++++++------------------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/schematic_api/api/routes.py b/schematic_api/api/routes.py index ec6e94208..324862f6a 100644 --- a/schematic_api/api/routes.py +++ b/schematic_api/api/routes.py @@ -292,47 +292,31 @@ def initalize_metadata_model(schema_url, data_model_labels): ) return metadata_model - -def get_temp_jsonld(schema_url): - # retrieve a JSON-LD via URL and store it in a temporary location - with urllib.request.urlopen(schema_url) as response: - with tempfile.NamedTemporaryFile( - delete=False, suffix=".model.jsonld" - ) as tmp_file: - shutil.copyfileobj(response, tmp_file) - - # get path to temporary JSON-LD file - return tmp_file.name - - -def get_temp_csv(schema_url): - # retrieve a CSV via URL and store it in a temporary location - with urllib.request.urlopen(schema_url) as response: - with tempfile.NamedTemporaryFile(delete=False, suffix=".model.csv") as tmp_file: - shutil.copyfileobj(response, tmp_file) - - # get path to temporary csv file - return tmp_file.name - - -def get_temp_pickle(graph_url: str) -> str: - # retrieve a pickle via URL and store it in a temporary location - with urllib.request.urlopen(graph_url) as response: - with tempfile.NamedTemporaryFile(delete=False, suffix=".pickle") as tmp_file: +def get_temp_file( + url: str, + suffix: str +) -> str: + """ + Retrieve a file via URL and store it in a temporary location + :param url str: URL to the file + :param suffix str: Suffix of the file + :return: Path to the temporary file + """ + with urllib.request.urlopen(url) as response: + with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp_file: shutil.copyfileobj(response, tmp_file) return tmp_file.name - def get_temp_model_path(schema_url): # Get model type: model_extension = pathlib.Path(schema_url).suffix.replace(".", "").upper() if model_extension == "CSV": - temp_path = get_temp_csv(schema_url) + temp_path = get_temp_file(schema_url, ".model.csv") elif model_extension == "JSONLD": - temp_path = get_temp_jsonld(schema_url) + temp_path = get_temp_file(schema_url, ".model.jsonld") elif model_extension == "PICKLE": - temp_path = get_temp_pickle(schema_url) + temp_path = get_temp_file(schema_url, ".model.pickle") else: raise ValueError( "Did not provide a valid model type CSV or JSONLD or PICKLE, please check submission and try again." From 445aad5cf024bec7c8fbdaca95305d034d7b06e8 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 15:16:58 -0700 Subject: [PATCH 113/124] remove unhelpful comments and whitespace --- schematic/visualization/tangled_tree.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/schematic/visualization/tangled_tree.py b/schematic/visualization/tangled_tree.py index 5686a0a46..7b86ae4a1 100644 --- a/schematic/visualization/tangled_tree.py +++ b/schematic/visualization/tangled_tree.py @@ -62,19 +62,13 @@ def __init__( parsed_data_model = None - # Instantiate Data Model Parser + # Instantiate Data Model Parser and generate graph if data_model_graph_pickle is None: data_model_parser = DataModelParser( path_to_data_model=self.path_to_json_ld, ) - - # Parse Model parsed_data_model = data_model_parser.parse_model() - - # Instantiate DataModelGraph data_model_grapher = DataModelGraph(parsed_data_model, data_model_labels) - - # Generate graph self.graph_data_model = data_model_grapher.graph else: From 0c4fad713b655df7841747ca7c228c56c25b996a Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 15:19:05 -0700 Subject: [PATCH 114/124] clarify test cases for attributes explorer --- tests/test_viz.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_viz.py b/tests/test_viz.py index 498a2edea..fb10cf49d 100644 --- a/tests/test_viz.py +++ b/tests/test_viz.py @@ -15,9 +15,13 @@ @pytest.fixture( params=[ + # Test case 1: pass jsonld and pickle file ("example.model.jsonld", "example.model.pickle"), + # Test case 2: only pass jsonld file ("example.model.jsonld", ""), + # Test case 3: don't provide jsonld or pickle file; should fail pytest.param(("", ""), marks=pytest.mark.xfail), + # Test case 4: pass only pickle file; should fail pytest.param(("", "example.model.pickle"), marks=pytest.mark.xfail), ] ) From f0b266dcd10af94fd202bf160b967abbc4d71f72 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 10 Sep 2024 15:23:39 -0700 Subject: [PATCH 115/124] run black --- schematic_api/api/routes.py | 7 +++---- tests/test_cli.py | 8 +++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/schematic_api/api/routes.py b/schematic_api/api/routes.py index 324862f6a..22b8b3cb8 100644 --- a/schematic_api/api/routes.py +++ b/schematic_api/api/routes.py @@ -292,10 +292,8 @@ def initalize_metadata_model(schema_url, data_model_labels): ) return metadata_model -def get_temp_file( - url: str, - suffix: str -) -> str: + +def get_temp_file(url: str, suffix: str) -> str: """ Retrieve a file via URL and store it in a temporary location :param url str: URL to the file @@ -308,6 +306,7 @@ def get_temp_file( return tmp_file.name + def get_temp_model_path(schema_url): # Get model type: model_extension = pathlib.Path(schema_url).suffix.replace(".", "").upper() diff --git a/tests/test_cli.py b/tests/test_cli.py index 3f0c90f50..dcb9ca9b6 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -52,9 +52,10 @@ def assert_expected_file(self, result, output_path): "output_path", [ # Test case 1: pickle file passed to output_path - "tests/data/example.model.pickle", + "tests/data/example.model.pickle", # Test case 2: jsonld file passed to output_path - "tests/data/example.model.jsonld"], + "tests/data/example.model.jsonld", + ], ids=["output_path_pickle", "output_path_jsonld"], ) @pytest.mark.parametrize( @@ -65,7 +66,8 @@ def assert_expected_file(self, result, output_path): # Test case 2: graph passed to output_type "graph", # Test case 3: both jsonld and graph are created - "all"], + "all", + ], ids=["output_type_jsonld", "output_type_graph", "output_type_all"], ) def test_schema_convert_cli(self, runner, output_path, output_type): From ec5e12194cf3fe1ff802b43328656e1e0b46db0b Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 28 Oct 2024 14:00:22 -0700 Subject: [PATCH 116/124] simpify message when export graph as pickle. --- schematic/utils/schema_utils.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/schematic/utils/schema_utils.py b/schematic/utils/schema_utils.py index 2523bb332..a0b260835 100644 --- a/schematic/utils/schema_utils.py +++ b/schematic/utils/schema_utils.py @@ -512,10 +512,7 @@ def export_graph(schema: dict, file_path: str) -> None: try: with open(file_path, "wb") as file: pickle.dump(schema, file) - logger.info( - "The data model graph was created and saved " - f"to a pickle file located at: '{file_path}'." - ) + logger.info(f"The graph was created and saved to '{file_path}'.") except SystemExit as error: logger.exception( f"The graph failed to save to '{file_path}'. Please check your file path again." From 5d5989033daf6b41879427dc88b28018e68c18af Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 28 Oct 2024 14:09:42 -0700 Subject: [PATCH 117/124] add tests for read_pickle --- tests/test_utils.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/test_utils.py b/tests/test_utils.py index 7280710a9..056507e60 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -467,6 +467,19 @@ def test_load_schema_org(self): actual_graph_keys = len(schema_org_schema["@graph"]) assert expected_graph_keys == actual_graph_keys + def TestReadPickle(self): + # Test that the function can read a pickle file + with tempfile.TemporaryDirectory() as tmpdir: + pickle_file = tmpdir + "/test.pkl" + with open(pickle_file, "wb") as f: + pickle.dump({"foo": "bar"}, f) + assert io_utils.read_pickle(pickle_file) == {"foo": "bar"} + + def test_read_pickle_invalid_file(self): + # Test that the function raises an error when trying to read an invalid file + with pytest.raises(FileNotFoundError): + io_utils.read_pickle("invalid_file.pkl") + class TestDfUtils: @pytest.mark.parametrize( From 79ad3d8d2a369b7784815d93d48b79443de3afdb Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 28 Oct 2024 14:13:41 -0700 Subject: [PATCH 118/124] add error handling and messaging to read_pickle --- schematic/utils/io_utils.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/schematic/utils/io_utils.py b/schematic/utils/io_utils.py index 487aff282..00da23bad 100644 --- a/schematic/utils/io_utils.py +++ b/schematic/utils/io_utils.py @@ -53,7 +53,11 @@ def load_schemaorg() -> Any: def read_pickle(file_path: str) -> Any: - """Read pickle file""" + """Read pickle file and return error if file not a .pkl or .pickle file""" + if not os.path.exists(file_path): + raise FileNotFoundError(f"File not found: {file_path}") + if not file_path.lower().endswith((".pkl", ".pickle")): + raise ValueError(f"File is not a pickle file: {file_path}") with open(file_path, "rb") as fle: data = pickle.load(fle) return data From 763dbddec33867809bd18a565c266ccd79837d30 Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 28 Oct 2024 14:15:26 -0700 Subject: [PATCH 119/124] add explanation to display label test --- tests/test_metadata.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 4986f3f7a..9e8b331cc 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -27,6 +27,8 @@ def metadata_model(helpers, data_model_labels): def metadata_model_display(helpers, data_model_labels): + # Test which labels are displayed to the user. + # Can be either 'display_label' or 'class_label' metadata_model = MetadataModel( inputMModelLocation=helpers.get_data_path("example.model.jsonld"), data_model_labels=data_model_labels, @@ -48,6 +50,7 @@ class TestMetadataModel: ) def test_get_component_requirements(self, helpers, as_graph, data_model_labels): # Instantiate MetadataModel + # Set up a metadata model with the given data model labels if data_model_labels == "class_label": meta_data_model = metadata_model(helpers, data_model_labels) else: From 288431ce5d37f4802027c8fccf40e5a611a5833c Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 28 Oct 2024 14:18:53 -0700 Subject: [PATCH 120/124] remove extra import and update docstring for create_manifests --- schematic/manifest/generator.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/schematic/manifest/generator.py b/schematic/manifest/generator.py index fd4db4ff8..d967930da 100644 --- a/schematic/manifest/generator.py +++ b/schematic/manifest/generator.py @@ -32,7 +32,6 @@ DisplayLabelType, extract_component_validation_rules, ) -from schematic.utils.df_utils import update_df, load_df from schematic.utils.io_utils import read_pickle from schematic.utils.validate_utils import rule_in_rule_list @@ -1685,7 +1684,7 @@ def create_manifests( Args: path_to_data_model (str): str path to data model data_model_graph_pickle (str, optional): path to pickled networkx MultiDiGraph object. Defaults to None. - graph_data_model (str, optional): An networkx MultiDiGraph object. Defaults to None. + graph_data_model (nx.MultiDiGraph, optional): An networkx MultiDiGraph object. Defaults to None. data_types (list): a list of data types access_token (str, optional): synapse access token. Required when getting an existing manifest. Defaults to None. dataset_ids (list, optional): a list of dataset ids when generating an existing manifest. Defaults to None. From 9ec9ddbeb82a01e4759803ca43a03f990a02afa3 Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 28 Oct 2024 14:26:51 -0700 Subject: [PATCH 121/124] add pickle file to test_create_manifests --- tests/test_manifest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_manifest.py b/tests/test_manifest.py index ade80fbe9..cdf5c5e88 100644 --- a/tests/test_manifest.py +++ b/tests/test_manifest.py @@ -759,6 +759,7 @@ def test_create_manifests( output_format="google_sheet", use_annotations=False, data_model_labels="class_label", + data_model_graph_pickle=helpers.get_data_path("example.model.pickle"), ) assert all_results == expected_result From 86e1646265a2b0688963c1a526e1cad0126100c3 Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 28 Oct 2024 14:31:35 -0700 Subject: [PATCH 122/124] run black --- schematic/utils/io_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematic/utils/io_utils.py b/schematic/utils/io_utils.py index 00da23bad..616a8c53a 100644 --- a/schematic/utils/io_utils.py +++ b/schematic/utils/io_utils.py @@ -9,7 +9,6 @@ from schematic import LOADER - def load_json(file_path: str) -> Any: """Load json document from file path or url @@ -62,6 +61,7 @@ def read_pickle(file_path: str) -> Any: data = pickle.load(fle) return data + def cleanup_temporary_storage( temporary_storage_directory: str, time_delta_seconds: int ) -> None: From d20c1fc8640917c7edb5ed1ecef68e0828d7e6fe Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 28 Oct 2024 14:46:03 -0700 Subject: [PATCH 123/124] run black --- schematic_api/api/routes.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/schematic_api/api/routes.py b/schematic_api/api/routes.py index 9cf3dc83a..a7fc78d47 100644 --- a/schematic_api/api/routes.py +++ b/schematic_api/api/routes.py @@ -223,6 +223,9 @@ def get_temp_file(url: str, suffix: str) -> str: """ with urllib.request.urlopen(url) as response: with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp_file: + shutil.copyfileobj(response, tmp_file) + return tmp_file.name + def get_temp_jsonld(schema_url): # retrieve a JSON-LD via URL and store it in a temporary location From 5a42f8a77bcd2d7732c52f0db14c1e35c6560503 Mon Sep 17 00:00:00 2001 From: afwillia Date: Mon, 28 Oct 2024 14:56:30 -0700 Subject: [PATCH 124/124] fix pylint issues --- schematic/utils/io_utils.py | 1 - schematic/visualization/attributes_explorer.py | 1 - 2 files changed, 2 deletions(-) diff --git a/schematic/utils/io_utils.py b/schematic/utils/io_utils.py index 616a8c53a..0fec4542a 100644 --- a/schematic/utils/io_utils.py +++ b/schematic/utils/io_utils.py @@ -6,7 +6,6 @@ import urllib.request from typing import Any import pickle -from schematic import LOADER def load_json(file_path: str) -> Any: diff --git a/schematic/visualization/attributes_explorer.py b/schematic/visualization/attributes_explorer.py index b1ca6e19e..90f335392 100644 --- a/schematic/visualization/attributes_explorer.py +++ b/schematic/visualization/attributes_explorer.py @@ -13,7 +13,6 @@ from schematic.utils.schema_utils import DisplayLabelType from schematic.utils.io_utils import load_json, read_pickle from schematic.schemas.data_model_parser import DataModelParser -from schematic.utils.schema_utils import DisplayLabelType logger = logging.getLogger(__name__)