Skip to content

Commit

Permalink
FileDownload widget: Allow callback to update filename (#1246)
Browse files Browse the repository at this point in the history
  • Loading branch information
maximlt authored and philippjfr committed Jun 19, 2020
1 parent 4f043f1 commit 16d49a0
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 5 deletions.
56 changes: 54 additions & 2 deletions panel/tests/widgets/test_misc.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import absolute_import, division, unicode_literals

from io import BytesIO
from io import BytesIO, StringIO
from base64 import b64encode

import numpy as np
Expand Down Expand Up @@ -49,6 +49,14 @@ def test_progress_bounds():


def test_file_download_label():
file_download = FileDownload()

assert file_download.label == 'No file set'

file_download = FileDownload(StringIO("data"), filename="abc.py")

assert file_download.label == "Download abc.py"

file_download = FileDownload(__file__)

assert file_download.label == 'Download test_misc.py'
Expand All @@ -66,6 +74,50 @@ def test_file_download_label():
assert file_download.label == 'Download abc.py'


def test_file_download_file():
with pytest.raises(ValueError):
FileDownload(StringIO("data"))

with pytest.raises(ValueError):
FileDownload(embed=True)

with pytest.raises(FileNotFoundError):
FileDownload("nofile", embed=True)

with pytest.raises(ValueError):
FileDownload(666, embed=True)

file_download = FileDownload("nofile")
with pytest.raises(FileNotFoundError):
file_download._clicks += 1


def test_file_download_callback():
file_download = FileDownload(callback=lambda: StringIO("data"), file="abc")

with pytest.raises(ValueError):
file_download._clicks += 1

file_download = FileDownload(callback=lambda: StringIO("data"), filename="abc.py")

assert file_download.data is None

file_download._clicks += 1
assert file_download.data is not None

file_download.data = None

def cb():
file_download.filename = "cba.py"
return StringIO("data")

file_download.callback = cb
file_download._clicks += 1

assert file_download.data is not None
assert file_download.filename == "cba.py"
assert file_download.label == "Download cba.py"

def test_file_download_data():
file_download = FileDownload(__file__, embed=True)

Expand All @@ -82,4 +134,4 @@ def test_file_download_data():

file_download.data = None
file_download._clicks += 1
assert file_download.data is not None
assert file_download.data is not None
11 changes: 8 additions & 3 deletions panel/widgets/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,15 +254,20 @@ def _update_embed(self):
@param.depends('_clicks', watch=True)
def _transfer(self):
if self.file is None and self.callback is None:
if self.embed:
raise ValueError('Must provide a file or a callback '
'if it is to be embedded.')
return

from ..param import ParamFunction
filename = self.filename
if self.callback is None:
fileobj = self.file
else:
fileobj = ParamFunction.eval(self.callback)
if isinstance(fileobj, str) and os.path.isfile(fileobj):
filename = self.filename
if isinstance(fileobj, str):
if not os.path.isfile(fileobj):
raise FileNotFoundError('File "%s" not found.' % fileobj)
with open(fileobj, 'rb') as f:
b64 = b64encode(f.read()).decode("utf-8")
if filename is None:
Expand All @@ -276,7 +281,7 @@ def _transfer(self):
raise ValueError('Must provide filename if file-like '
'object is provided.')
else:
raise ValueError('Cannot transfer unknown file type %s' %
raise ValueError('Cannot transfer unknown object of type %s' %
type(fileobj).__name__)

ext = filename.split('.')[-1]
Expand Down

0 comments on commit 16d49a0

Please sign in to comment.