Skip to content

Commit

Permalink
Merge branch 'master' into feat/tags
Browse files Browse the repository at this point in the history
  • Loading branch information
tmichela authored Dec 17, 2024
2 parents ec8ec12 + 6aea7bf commit ce556c3
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 13 deletions.
10 changes: 5 additions & 5 deletions .github/dependabot/constraints.txt
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
EXtra-data==1.18.0
ipython==8.29.0
ipython==8.30.0
kafka-python==2.0.2
matplotlib==3.9.2
matplotlib==3.10.0
mplcursors==0.6
mpl-pan-zoom==1.0.0
numpy==2.1.3
numpy==2.2.0
openpyxl==3.1.5
pandas==2.2.3
pyflakes==3.2.0
PyQt5==5.15.11
pytest==8.3.3
pytest==8.3.4
pytest-qt==4.4.0
pytest-xvfb==3.0.0
QScintilla==2.13.0
supervisor==4.2.5
termcolor==2.5.0
xarray==2024.10.0
xarray==2024.11.0
13 changes: 11 additions & 2 deletions damnit/ctxsupport/ctxrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,11 @@ def generate_thumbnail(image):
fig.subplots_adjust(left=0, right=1, bottom=0, top=1)
vmin = np.nanquantile(image, 0.01)
vmax = np.nanquantile(image, 0.99)
ax.imshow(image, vmin=vmin, vmax=vmax, extent=(0, 1, 1, 0))
if isinstance(image, np.ndarray):
ax.imshow(image, vmin=vmin, vmax=vmax)
else:
# Use DataArray's own plotting method
image.plot(ax=ax, vmin=vmin, vmax=vmax, add_colorbar=False)
ax.axis('tight')
ax.axis('off')
ax.margins(0, 0)
Expand Down Expand Up @@ -519,7 +523,12 @@ def summarise(self, name):
if data.ndim == 0:
return data
elif data.ndim == 2:
return generate_thumbnail(np.nan_to_num(data))
if isinstance(data, np.ndarray):
data = np.nan_to_num(data)
else:
data = data.fillna(0)

return generate_thumbnail(data)
else:
return f"{data.dtype}: {data.shape}"

Expand Down
21 changes: 18 additions & 3 deletions damnit/gui/editor.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import sys
import traceback
from enum import Enum
from io import StringIO
from pathlib import Path
Expand Down Expand Up @@ -26,12 +27,17 @@ class ContextFileCheckerThread(QThread):
# ContextTestResult, traceback, lineno, offset, checked_code
check_result = pyqtSignal(object, str, int, int, str)

def __init__(self, code, db_dir, context_python, parent=None):
def __init__(self, code, db_dir, context_python, context_getter, parent=None):
super().__init__(parent)
self.code = code
self.db_dir = db_dir
self.context_python = context_python

# This is a hack to allow us to test throwing an exception when checking
# the context file. It'll always be get_context_file() except when
# replaced with a Mock by the tests.
self.context_getter = context_getter

def run(self):
error_info = None

Expand All @@ -51,7 +57,16 @@ def run(self):
ctx_path = Path(ctx_file.name)
ctx_path.write_text(self.code)

ctx, error_info = get_context_file(ctx_path, self.context_python)
try:
ctx, error_info = self.context_getter(ctx_path, self.context_python)
except:
# Not a failure to evalute the context file, but a failure
# to *attempt* to evaluate the context file (e.g. because of
# a missing dependency).
help_msg = "# This is a partial error, please check the terminal for the full error message and ask for help from DA or the DOC."
traceback_str = f"{help_msg}\n\n{traceback.format_exc()}"
self.check_result.emit(ContextTestResult.ERROR, traceback_str, 0, 0, self.code)
return

if error_info is not None:
stacktrace, lineno, offset = error_info
Expand Down Expand Up @@ -110,7 +125,7 @@ def __init__(self):

def launch_test_context(self, db):
context_python = db.metameta.get("context_python")
thread = ContextFileCheckerThread(self.text(), db.path.parent, context_python, parent=self)
thread = ContextFileCheckerThread(self.text(), db.path.parent, context_python, get_context_file, parent=self)
thread.check_result.connect(self.on_test_result)
thread.finished.connect(thread.deleteLater)
thread.start()
Expand Down
3 changes: 3 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
Fixed:

- Added back grid lines for plots of `DataArray`'s (!334).
- Fixed thumbnails of 2D `DataArray`'s to match what is displayed when the
variable is plotted (!355).
- Fixed crashes when the context file environment is missing dependencies (!356).

## [0.1.4]

Expand Down
12 changes: 9 additions & 3 deletions tests/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,13 +325,18 @@ def foo(run): return xr.DataArray([1, 2, 3])

figure_code = """
import numpy as np
import xarray as xr
from damnit_ctx import Variable
from matplotlib import pyplot as plt
@Variable("2D array")
@Variable("2D ndarray")
def twodarray(run):
return np.random.rand(1000, 1000)
@Variable("2D xarray")
def twodxarray(run):
return xr.DataArray(np.random.rand(100, 100))
@Variable(title="Axes")
def axes(run):
_, ax = plt.subplots()
Expand Down Expand Up @@ -359,8 +364,9 @@ def figure(run):
assert f["axes/data"].ndim == 3

# Test that the summaries are the right size
twodarray_png = Image.open(io.BytesIO(f[".reduced/twodarray"][()]))
assert np.asarray(twodarray_png).shape == (THUMBNAIL_SIZE, THUMBNAIL_SIZE, 4)
for var in ["twodarray", "twodxarray"]:
png = Image.open(io.BytesIO(f[f".reduced/{var}"][()]))
assert np.asarray(png).shape == (THUMBNAIL_SIZE, THUMBNAIL_SIZE, 4)

figure_png = Image.open(io.BytesIO(f[".reduced/figure"][()]))
assert max(np.asarray(figure_png).shape) == THUMBNAIL_SIZE
Expand Down
10 changes: 10 additions & 0 deletions tests/test_gui.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import re
import sys
import textwrap
from contextlib import contextmanager
from pathlib import Path
Expand Down Expand Up @@ -151,6 +152,15 @@ def test_editor(mock_db, mock_ctx, qtbot):
win.save_context()
assert ctx_path.read_text() == warning_code

# Throwing an exception when evaluating the context file in a different
# environment should be handled gracefully. This can happen if running the
# ctxrunner itself fails, e.g. because of a missing dependency.
db.metameta["context_python"] = sys.executable
with qtbot.waitSignal(editor.check_result) as sig, \
patch("damnit.gui.editor.get_context_file", side_effect=Exception("foo")):
editor.launch_test_context(db)
assert sig.args[0] == ContextTestResult.ERROR

def test_settings(mock_db_with_data, mock_ctx, tmp_path, monkeypatch, qtbot):
db_dir, db = mock_db_with_data
monkeypatch.chdir(db_dir)
Expand Down

0 comments on commit ce556c3

Please sign in to comment.