Skip to content

Commit

Permalink
Add data without session corruption (#111)
Browse files Browse the repository at this point in the history
* Add data without session corruption

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Add a test on session when adding data

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Move function to glue_utils

* Improving the readability of nested_compare

Co-authored-by: martinRenou <[email protected]>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: martinRenou <[email protected]>
  • Loading branch information
3 people authored Jul 5, 2023
1 parent 81d3411 commit c366931
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 20 deletions.
34 changes: 22 additions & 12 deletions gluepyter/glue_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import warnings
from pathlib import Path
from typing import TYPE_CHECKING, Dict, Optional, Tuple

from glue.core.link_helpers import LinkSame
from glue.core.state import GlueSerializer
import glue_jupyter as gj
Expand Down Expand Up @@ -356,29 +355,40 @@ def add_data(self, file_path: str) -> None:
assert os.path.exists(relative_path)

data = self.app.load_data(str(relative_path))
self._data[data.label] = data

# We generate the data representation and merge it into our ycontent
serializer = GlueSerializer(data)
serialized_data = serializer.dumpo()
# Serialize the data on its own (without other context).
data_serializer = GlueSerializer(data)
data_serializer.dumpo()

# Serialize the previous data without the new one to create a context.
previous_data_serializer = GlueSerializer(self._data)
previous_data_serializer.dumpo()

# We generate the data representation in the previous data context.
serialized_data = [
(previous_data_serializer.id(obj), previous_data_serializer.do(obj))
for oid, obj in list(data_serializer._objs.items())
]
serialized_data = dict(serialized_data)

contents = self._document.contents

# Inject the main data repr
contents[data.label] = serialized_data["__main__"]
# Inject all components
for key, value in serialized_data.items():
if key != "__main__":
contents[key] = value

# Inject the label in the data collection
contents["DataCollection"]["data"].append(data.label)
contents["DataCollection"]["cids"].extend(
cid for cid, comp in serialized_data["__main__"]["components"]
data_collection_name: str = contents.get("__main__", {}).get("data", "")
contents[data_collection_name]["data"].append(data.label)
contents[data_collection_name]["cids"].extend(
cid for cid, comp in serialized_data[data.label]["components"]
)
contents["DataCollection"]["components"].extend(
comp for cid, comp in serialized_data["__main__"]["components"]
contents[data_collection_name]["components"].extend(
comp for cid, comp in serialized_data[data.label]["components"]
)

self._data[data.label] = data
self._document.set(json.dumps(contents))

def _load_data(self) -> None:
Expand Down
41 changes: 34 additions & 7 deletions gluepyter/glue_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@
load_plugins()


class ErrorWidget:
"""Wrapper of a HTML widget for showing error message"""

def __init__(self, e: Exception, path: str) -> None:
value = f"{type(e).__name__} at line {e.__traceback__.tb_lineno} of {path}: {e}"
self._widget = HTML(value=value)

def show(self):
display(self._widget)


def get_function_info(function_or_helper):
item_info: Dict[str, Dict] = {}
attributes = ["description", "labels1", "labels2", "display"]
Expand Down Expand Up @@ -67,12 +78,28 @@ def get_advanced_links():
return advanced_links


class ErrorWidget:
"""Wrapper of a HTML widget for showing error message"""
def nested_compare(value1, value2):
# Compare lists
if isinstance(value1, list) and isinstance(value2, list):
if not len(value1) == len(value2):
return False

def __init__(self, e: Exception, path: str) -> None:
value = f"{type(e).__name__} at line {e.__traceback__.tb_lineno} of {path}: {e}"
self._widget = HTML(value=value)
for v1, v2 in zip(value1, value2):
if not nested_compare(v1, v2):
return False

def show(self):
display(self._widget)
return True

# Compare dict
if isinstance(value1, dict) and isinstance(value2, dict):
for k1, v1 in value1.items():
if k1 not in value2.keys():
return False

if not nested_compare(v1, value2[k1]):
return False

return True

# Compare immutable
return value1 == value2
32 changes: 31 additions & 1 deletion gluepyter/tests/test_glue_session.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import y_py as Y
from gluepyter.glue_session import SharedGlueSession
from copy import deepcopy
from pathlib import Path
from ipywidgets import Output
from gluepyter.glue_session import SharedGlueSession
from gluepyter.glue_utils import nested_compare


def test_init(session_path):
Expand Down Expand Up @@ -61,6 +64,33 @@ def test__read_view_state(yglue_session):
assert len(state) > 0


def test_add_data(yglue_session):
yglue_session._load_data()
file_path = Path(__file__).parents[2] / "examples" / "w6_psc.vot"

contents = deepcopy(yglue_session._document.contents)
yglue_session.add_data(file_path)
updated_contents = yglue_session._document.contents

assert "w6_psc" in updated_contents.keys()

# Assert there is no change in previous structure
for key, value in contents.items():
if key == "DataCollection":
continue
assert key in updated_contents.keys()
assert nested_compare(value, updated_contents[key])

# Compare the DataCollection
for key, value in contents["DataCollection"].items():
if key == "data" or key == "cids" or key == "components":
assert not nested_compare(value, updated_contents["DataCollection"][key])
else:
assert nested_compare(value, updated_contents["DataCollection"][key])

assert "w6_psc" in updated_contents["DataCollection"]["data"]


def test_add_identity_link(yglue_session, identity_link):
yglue_session._load_data()
change = {"LinkTest": {"action": "add", "newValue": identity_link}}
Expand Down

0 comments on commit c366931

Please sign in to comment.