From 94788db11be32b4ab73104b8c8a57ee56ade4234 Mon Sep 17 00:00:00 2001 From: Santiago Balestrini Date: Mon, 26 Jul 2021 13:14:02 -0400 Subject: [PATCH 1/8] Bumped version back up to 0.18.0 and minor tweak to ci.yml --- .github/workflows/ci.yml | 6 +++--- src/pymbe/_version.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b911262..4884ed00 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,12 +9,12 @@ on: workflow_dispatch: null env: + CACHE_EPOCH: 0 + CONDA_EXE: mamba + PIP_DISABLE_PIP_VERSION_CHECK: '1' PYTHONIOENCODING: utf-8 PYTHONUNBUFFERED: '1' - PIP_DISABLE_PIP_VERSION_CHECK: '1' - CONDA_EXE: mamba SKIP_CONDA_PREFLIGHT: 1 - CACHE_EPOCH: 0 jobs: build: diff --git a/src/pymbe/_version.py b/src/pymbe/_version.py index c6eae9f8..1317d755 100644 --- a/src/pymbe/_version.py +++ b/src/pymbe/_version.py @@ -1 +1 @@ -__version__ = "0.17.1" +__version__ = "0.18.0" From a9ae63ec290a5e8073ee4a471ec02da459a0c38c Mon Sep 17 00:00:00 2001 From: Santiago Balestrini Date: Mon, 26 Jul 2021 13:18:19 -0400 Subject: [PATCH 2/8] Fixed bad string concatenations from black --- src/pymbe/client.py | 2 +- src/pymbe/graph/rdf.py | 2 +- tests/interpretation/test_graph_visit_orderings.py | 2 +- tests/query/test_feature_queries.py | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pymbe/client.py b/src/pymbe/client.py index 70024a77..ae79c983 100644 --- a/src/pymbe/client.py +++ b/src/pymbe/client.py @@ -203,7 +203,7 @@ def _retrieve_data(self, url: str) -> List[Dict]: if not response.ok: raise requests.HTTPError( - f"Failed to retrieve elements from '{url}', " f"reason: {response.reason}" + f"Failed to retrieve elements from '{url}', reason: {response.reason}" ) result += response.json() diff --git a/src/pymbe/graph/rdf.py b/src/pymbe/graph/rdf.py index d12d97a8..1620c3e5 100644 --- a/src/pymbe/graph/rdf.py +++ b/src/pymbe/graph/rdf.py @@ -33,7 +33,7 @@ def import_context(self, jsonld_item: dict) -> dict: data = response.json() if "@context" not in data: raise ValueError( - "Download context does not have a " f"@context key: {list(data.keys())}" + f"Download context does not have a @context key: {list(data.keys())}" ) self._cached_contexts[context_url] = data["@context"] jsonld_item["@context"].update(self._cached_contexts[context_url]) diff --git a/tests/interpretation/test_graph_visit_orderings.py b/tests/interpretation/test_graph_visit_orderings.py index 2eff2ba1..b5644968 100644 --- a/tests/interpretation/test_graph_visit_orderings.py +++ b/tests/interpretation/test_graph_visit_orderings.py @@ -97,7 +97,7 @@ def test_feature_sequence_templates4(simple_parts_lpg, simple_parts_stable_names f"{SIMPLE_MODEL}Power Group: Part::Power User: Part <>" ] power_in_port_id = qualified_name_to_id[ - f"{SIMPLE_MODEL}Power Group: Part::Power User: " f"Part::Power In: Port <>" + f"{SIMPLE_MODEL}Power Group: Part::Power User: Part::Power In: Port <>" ] print(seq_templates) diff --git a/tests/query/test_feature_queries.py b/tests/query/test_feature_queries.py index 2dea2aae..372ef03a 100644 --- a/tests/query/test_feature_queries.py +++ b/tests/query/test_feature_queries.py @@ -109,7 +109,7 @@ def test_banded_graph_paths3(simple_parts_lpg, simple_parts_stable_names): power_group_id = qualified_name_to_id[f"{SIMPLE_MODEL}Power Group: Part <>"] power_in_port_id = qualified_name_to_id[ - f"{SIMPLE_MODEL}Power Group: Part::Power User: " f"Part::Power In: Port <>" + f"{SIMPLE_MODEL}Power Group: Part::Power User: Part::Power In: Port <>" ] power_out_id = qualified_name_to_id[ f"{SIMPLE_MODEL}Power Group: Part::Power Source: Part::Power Out: Port <>" @@ -200,7 +200,7 @@ def test_type_multiplicity_rollup2(simple_parts_lpg, simple_parts_stable_names): *_, qualified_name_to_id = simple_parts_stable_names power_out_id = qualified_name_to_id[ - f"{SIMPLE_MODEL}Power Group: Part::Power Source: " f"Part::Power Out: Port <>" + f"{SIMPLE_MODEL}Power Group: Part::Power Source: Part::Power Out: Port <>" ] power_in_id = qualified_name_to_id[ f"{SIMPLE_MODEL}Power Group: Part::Power User: Part::Power In: Port <>" From 3916a9e35c9ef52693ce903a553a85a8e30c1c5c Mon Sep 17 00:00:00 2001 From: Santiago Balestrini Date: Tue, 3 Aug 2021 21:28:55 -0400 Subject: [PATCH 3/8] Fixed issue with client due to changing API server and python API clients not working --- src/pymbe/client.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/pymbe/client.py b/src/pymbe/client.py index ae79c983..49e60224 100644 --- a/src/pymbe/client.py +++ b/src/pymbe/client.py @@ -107,13 +107,12 @@ def _make_projects_api(self): @trt.default("projects") def _make_projects(self): - projects = self._projects_api.get_projects() - def process_project_safely(project) -> dict: # protect against projects that can't be parsed try: + name = project["name"] created = parser.parse( - " ".join(project.name.split()[-6:]), + " ".join(name.split()[-6:]), tzinfos=TIMEZONES, ).astimezone(timezone.utc) except ValueError: @@ -121,11 +120,13 @@ def process_project_safely(project) -> dict: return dict() return dict( created=created, - full_name=project.name, - name=" ".join(project.name.split()[:-6]), + full_name=name, + name=" ".join(name.split()[:-6]), ) - results = {project.id: process_project_safely(project) for project in projects} + projects = self._retrieve_data(self.projects_url) + + results = {project["@id"]: process_project_safely(project) for project in projects} return { project_id: project_data @@ -180,6 +181,10 @@ def _update_elements_from_file(self, change: trt.Bunch = None): def host(self): return f"{self.host_url}:{self.host_port}" + @property + def projects_url(self): + return f"{self.host}/projects" + @property def elements_url(self): if not self.paginate: @@ -188,7 +193,7 @@ def elements_url(self): "records at a time! True pagination is not supported yet." ) return ( - (f"{self.host}/projects/{self.selected_project}/commits/{self.selected_commit}") + (f"{self.projects_url}/{self.selected_project}/commits/{self.selected_commit}") + f"/elements?page[size]={self.page_size}" if self.page_size else "" From e4b30bc591bfe11d8215f1e4f46560f7630f84bf Mon Sep 17 00:00:00 2001 From: Santiago Balestrini Date: Tue, 3 Aug 2021 21:34:16 -0400 Subject: [PATCH 4/8] Changed version to 0.17.2 --- src/pymbe/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pymbe/_version.py b/src/pymbe/_version.py index 1317d755..337a1e73 100644 --- a/src/pymbe/_version.py +++ b/src/pymbe/_version.py @@ -1 +1 @@ -__version__ = "0.18.0" +__version__ = "0.17.2" From a0c7c5ebe76e4724ef23cffc33702e85175233fa Mon Sep 17 00:00:00 2001 From: Santiago Balestrini Date: Tue, 3 Aug 2021 22:37:37 -0400 Subject: [PATCH 5/8] Added a vscode command to the AP file --- anaconda-project.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/anaconda-project.yml b/anaconda-project.yml index e641683c..f3a9c230 100644 --- a/anaconda-project.yml +++ b/anaconda-project.yml @@ -81,6 +81,10 @@ commands: notebooks/Tutorial.ipynb: env_spec: user notebook: notebooks/Tutorial.ipynb + vscode: + env_spec: developer + unix: code . + windows: code . channels: - conda-forge From 6345fc9d938635114dcf56628a24ac4ddede1a1f Mon Sep 17 00:00:00 2001 From: Santiago Balestrini Date: Tue, 3 Aug 2021 23:21:46 -0400 Subject: [PATCH 6/8] GH-26 removed SysML-v2-API-Python-Client from AP file --- anaconda-project.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/anaconda-project.yml b/anaconda-project.yml index f3a9c230..7d6dc081 100644 --- a/anaconda-project.yml +++ b/anaconda-project.yml @@ -7,7 +7,6 @@ description: | variables: MAX_LINE_LENGTH: 99 - SYSML_V2_API_REPO: https://github.com/Systems-Modeling/SysML-v2-API-Python-Client.git@2021-05 commands: lab: @@ -20,10 +19,9 @@ commands: env_spec: developer unix: | git submodule update --init - pip install git+{{SYSML_V2_API_REPO}} --no-dependencies pip install -e . --no-dependencies windows: | - git submodule update --init & pip install git+{{SYSML_V2_API_REPO}} --no-dependencies & pip install -e . --no-dependencies + git submodule update --init & pip install -e . --no-dependencies lint: description: lint the code env_spec: developer From 8141b08e6111a5eea45dae59cba6864a742d00a2 Mon Sep 17 00:00:00 2001 From: Santiago Balestrini Date: Tue, 3 Aug 2021 23:22:28 -0400 Subject: [PATCH 7/8] GH-26 removed SysML-v2-API-Python-Client from pymbe python files --- src/pymbe/client.py | 66 +++++++------------------------------- src/pymbe/label.py | 6 ++-- src/pymbe/widget/client.py | 6 ++-- 3 files changed, 17 insertions(+), 61 deletions(-) diff --git a/src/pymbe/client.py b/src/pymbe/client.py index 49e60224..811755ed 100644 --- a/src/pymbe/client.py +++ b/src/pymbe/client.py @@ -6,7 +6,6 @@ from warnings import warn import requests -import sysml_v2_api_client as sysml2 import traitlets as trt from dateutil import parser from ipywidgets.widgets.trait_types import TypedTuple @@ -64,11 +63,6 @@ class SysML2Client(trt.HasTraits): paginate = trt.Bool(default_value=True) - _api_configuration: sysml2.Configuration = trt.Instance(sysml2.Configuration) - _commits_api: sysml2.CommitApi = trt.Instance(sysml2.CommitApi) - _elements_api: sysml2.ElementApi = trt.Instance(sysml2.ElementApi) - _projects_api: sysml2.ProjectApi = trt.Instance(sysml2.ProjectApi) - folder_path: Path = trt.Instance(Path, allow_none=True) json_files: Tuple[Path] = TypedTuple(trt.Instance(Path)) json_file: Path = trt.Instance(Path, allow_none=True) @@ -82,29 +76,6 @@ class SysML2Client(trt.HasTraits): _next_url_regex = re.compile(r'<(http://.*)>; rel="next"') - @trt.default("_api_configuration") - def _make_api_configuration(self): - return sysml2.Configuration(host=self.host) - - @trt.default("_commits_api") - def _make_commits_api(self): - with sysml2.ApiClient(self._api_configuration) as client: - api = sysml2.CommitApi(client) - return api - - @trt.default("_elements_api") - def _make_elements_api(self): - with sysml2.ApiClient(self._api_configuration) as client: - api = sysml2.ElementApi(client) - return api - - @trt.default("_projects_api") - def _make_projects_api(self): - with sysml2.ApiClient(self._api_configuration) as client: - # TODO: add check for a bad URL not to make this call - api = sysml2.ProjectApi(client) - return api - @trt.default("projects") def _make_projects(self): def process_project_safely(project) -> dict: @@ -136,19 +107,6 @@ def process_project_safely(project) -> dict: @trt.observe("host_url", "host_port") def _update_api_configuration(self, *_): - old_api_configuration = self._api_configuration - self._api_configuration = self._make_api_configuration() - if old_api_configuration: - del old_api_configuration - - @trt.observe("_api_configuration") - def _update_apis(self, *_): - for api_type in ("commit", "element", "project"): - api_attr = f"_{api_type}s_api" - old_api = getattr(self, api_attr) - api_maker = getattr(self, f"_make{api_attr}") - setattr(self, api_attr, api_maker()) - del old_api self.projects = self._make_projects() @trt.observe("selected_commit") @@ -185,6 +143,10 @@ def host(self): def projects_url(self): return f"{self.host}/projects" + @property + def commits_url(self): + return f"{self.projects_url}/{self.selected_project}/commits" + @property def elements_url(self): if not self.paginate: @@ -192,12 +154,12 @@ def elements_url(self): "By default, disabling pagination still retrieves 100 " "records at a time! True pagination is not supported yet." ) - return ( - (f"{self.projects_url}/{self.selected_project}/commits/{self.selected_commit}") - + f"/elements?page[size]={self.page_size}" - if self.page_size - else "" - ) + if not self.selected_project: + raise SystemError("No selected project!") + if not self.selected_commit: + raise SystemError("No selected commit!") + arguments = f"?page[size]={self.page_size}" if self.page_size else "" + return f"{self.commits_url}/{self.selected_commit}/elements{arguments}" @lru_cache def _retrieve_data(self, url: str) -> List[Dict]: @@ -226,13 +188,7 @@ def _retrieve_data(self, url: str) -> List[Dict]: return result def _get_project_commits(self): - # TODO: add more info about the commit when API provides it - return [ - commit.id - for commit in self._commits_api.get_commits_by_project( - self.selected_project, - ) - ] + return {commit["@id"]: commit for commit in self._retrieve_data(self.commits_url)} def _download_elements(self): elements = self._retrieve_data(self.elements_url) diff --git a/src/pymbe/label.py b/src/pymbe/label.py index 8b776ec7..2206a5b4 100644 --- a/src/pymbe/label.py +++ b/src/pymbe/label.py @@ -73,7 +73,6 @@ def get_label_for_expression( return f"FRE.{referent_name}" prefix = "" - if "input" in expression._data: inputs = [ expression._model.elements[an_input["@id"]] for an_input in expression._data["input"] @@ -82,7 +81,7 @@ def get_label_for_expression( inputs = [] if isinstance(inputs, Element): inputs = [inputs] - input_names = [an_input.name for an_input in inputs] + input_names = [an_input.name for an_input in inputs if an_input.name] try: result: Element = expression.result except AttributeError: @@ -112,7 +111,8 @@ def get_label_for_expression( path_step_names.append(refered.get("name") or refered._id) prefix = ".".join(path_step_names) - return f"""{prefix} ({", ".join(input_names)}) => {result.name}""" + inputs = f""" ({", ".join(input_names)})""" if input_names else "" + return f"""{prefix}{inputs} => {result.name or "Unnamed Result"}""" def get_label_for_multiplicity(multiplicity: Element) -> str: diff --git a/src/pymbe/widget/client.py b/src/pymbe/widget/client.py index 6abe3878..c02d84aa 100644 --- a/src/pymbe/widget/client.py +++ b/src/pymbe/widget/client.py @@ -115,7 +115,7 @@ def _make_project_selector(self): def _make_commit_selector(self): selector = ipyw.Dropdown( description="Commit:", - options=self._get_project_commits(), + options=list(self._get_project_commits()), ) trt.link((selector, "value"), (self, "selected_commit")) return selector @@ -143,13 +143,13 @@ def _make_progress_bar(self): progress_bar.layout.visibility = "hidden" return progress_bar - @trt.observe("_api_configuration") + @trt.observe("projects") def _update_apis(self, *_): self.project_selector.options = self._get_project_options() @trt.observe("selected_project") def _update_commit_options(self, *_): - self.commit_selector.options = self._get_project_commits() + self.commit_selector.options = list(self._get_project_commits()) def _download_elements(self, *_): progress = self.progress_bar From fd082d41a3ac6d498e172b531fc8e1fd2bbf3fef Mon Sep 17 00:00:00 2001 From: Santiago Balestrini Date: Tue, 3 Aug 2021 23:22:46 -0400 Subject: [PATCH 8/8] Fixed issues with tests --- tests/client/test_client_loading.py | 9 +++------ tests/interpretation/test_calculation_ordering.py | 15 ++++++++------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/tests/client/test_client_loading.py b/tests/client/test_client_loading.py index 6b72b98e..f461a49f 100644 --- a/tests/client/test_client_loading.py +++ b/tests/client/test_client_loading.py @@ -1,6 +1,5 @@ import pytest import requests -import urllib3 from tests.conftest import all_kerbal_names, kerbal_client, kerbal_ids_by_type @@ -34,9 +33,9 @@ def test_client_load_find_types(kerbal_ids_by_type): def test_bad_connection(kerbal_client): - with pytest.raises(urllib3.exceptions.MaxRetryError) as exc: + with pytest.raises(requests.exceptions.ConnectionError) as exc: kerbal_client.host_url = "http://some.bad.url" - assert "Max retries exceeded" in exc.value.args[0] + assert exc.value.args[0].url == "/projects" @pytest.mark.skipif( @@ -52,9 +51,7 @@ def test_remote_connection(kerbal_client): client.page_size = 20 client.selected_project = list(client.projects)[0] - client.selected_commit = client._commits_api.get_commits_by_project(client.selected_project)[ - 0 - ].id + client.selected_commit = list(client._get_project_commits())[0] client._download_elements() model = client.model diff --git a/tests/interpretation/test_calculation_ordering.py b/tests/interpretation/test_calculation_ordering.py index 167a8261..021b6ef2 100644 --- a/tests/interpretation/test_calculation_ordering.py +++ b/tests/interpretation/test_calculation_ordering.py @@ -1,7 +1,5 @@ -import logging - from pymbe.interpretation.calc_dependencies import generate_execution_order -from pymbe.interpretation.results import * +from tests.conftest import kerbal_lpg, kerbal_random_stage_5_complete, kerbal_stable_names ROCKET_BUILDING = "Model::Kerbal::Rocket Building::" PARTS_LIBRARY = "Model::Kerbal::Parts Library::" @@ -16,19 +14,22 @@ def test_kerbal_calc_order1(kerbal_lpg, kerbal_random_stage_5_complete, kerbal_s number_liquid_stages = len(kerbal_random_stage_5_complete[liquid_stage_type]) + if number_liquid_stages < 1: + print(">>> Didn't make any liquid stages!!!") + dcg = generate_execution_order(kerbal_lpg) # the execution order will be ordered for examination sum_1_result = qualified_name_to_id[ f"{ROCKET_BUILDING}Liquid Stage::Full Mass: Real::+ (sum (engines.Mass" - + f" (FRE.engines)), sum (tanks.Full Mass (FRE.tanks))) => $result::sum" - + f" (tanks.Full Mass (FRE.tanks)) => $result::tanks.Full Mass (FRE.tanks) <>" + " (FRE.engines)), sum (tanks.Full Mass (FRE.tanks))) => $result::sum" + " (tanks.Full Mass (FRE.tanks)) => $result::tanks.Full Mass (FRE.tanks) <>" ] top_plus = qualified_name_to_id[ f"{ROCKET_BUILDING}Liquid Stage::Full Mass: Real::+ (sum (engines.Mass " - f"(FRE.engines)), sum (tanks.Full Mass (FRE.tanks))) => " - f"$result <>" + "(FRE.engines)), sum (tanks.Full Mass (FRE.tanks))) => " + "$result <>" ] sum_1_in_dcg = None