Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Render save() server-side via ginga
Use the ginga viewer's save_rgb_image_as_file renderer instead of writing
out the JPEG-encoded widget buffer. This produces a file in the format
implied by the extension (e.g. a real PNG for a .png filename) and does
not depend on a running browser. The overwrite guard is unchanged.

Co-written with Claude Opus 4.8
  • Loading branch information
mwcraig committed Jul 4, 2026
commit 60287b794d45954c023f35c1bd75c9048fc47c37
7 changes: 3 additions & 4 deletions astrowidgets/ginga.py
Original file line number Diff line number Diff line change
Expand Up @@ -702,10 +702,9 @@ def save(self, filename, overwrite=False, **kwargs):
overwrite : bool, optional
If `True`, overwrite an existing file.
"""
# The widget value is already PNG-encoded, so just write it out. This
# requires a running browser to have populated the buffer.
if not overwrite and Path(filename).exists():
raise FileExistsError(f'File {filename} exists and overwrite=False')

with open(filename, 'wb') as f:
f.write(self._jup_img.value)
# Ginga renders the view server-side, so this works without a running
# browser and honors the image format implied by the file extension.
self._viewer.save_rgb_image_as_file(str(filename))
10 changes: 0 additions & 10 deletions astrowidgets/tests/test_widget_api_ginga.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,3 @@ def test_center_on_skycoord_updates_viewport():
class TestGingaWidget(ImageAPITest):
image_widget_class = ImageWidget
cursor_error_classes = (ValueError, TraitError)

@pytest.mark.skip(reason="Saving requires a running browser to populate "
"the image buffer.")
def test_save(self, tmp_path):
pass

@pytest.mark.skip(reason="Saving requires a running browser to populate "
"the image buffer.")
def test_save_overwrite(self, tmp_path):
pass