Skip to content
This repository has been archived by the owner on Feb 16, 2023. It is now read-only.

display(HTML(...)) For local link doesn't download on single click #152

Closed
Tracked by #2422
Yanay1 opened this issue Jun 4, 2021 · 10 comments
Closed
Tracked by #2422

display(HTML(...)) For local link doesn't download on single click #152

Yanay1 opened this issue Jun 4, 2021 · 10 comments
Labels
bug Something isn't working
Milestone

Comments

@Yanay1
Copy link

Yanay1 commented Jun 4, 2021

Description

display + HTML local download links don't trigger a download.

Reproduce

Reproduced on a clean install of retrolab (according to https://jupyterlab.readthedocs.io/en/latest/getting_started/issue.html).

Code:

from IPython.display import display, HTML, Javascript
path = "...ipynb"
out_html = """
<p>Click <a href="{}" target="_blank">here</a>
to download the file.</p>
""".format(zip_path)

display(HTML(out_html))

Screenshot:
Screen Shot 2021-06-03 at 6 05 44 PM

Expected behavior

Clicking the link should initiate the download of the file, but does nothing. You need to middle click the link to download. On classic notebook, you can just click.

Context

  • Operating System and version: Mac OS
  • Browser and version: Chrome
  • JupyterLab version: 3.0.16
Troubleshoot Output
sys.path:
	...opt/miniconda3/envs/jlab-test/bin
	...opt/miniconda3/envs/jlab-test/lib/python39.zip
	...opt/miniconda3/envs/jlab-test/lib/python3.9
	...miniconda3/envs/jlab-test/lib/python3.9/lib-dynload
	...miniconda3/envs/jlab-test/lib/python3.9/site-packages

sys.executable:
.../miniconda3/envs/jlab-test/bin/python

sys.version:
3.9.4 | packaged by conda-forge | (default, May 10 2021, 22:13:15)
[Clang 11.1.0 ]

platform.platform():
macOS-10.15.7-x86_64-i386-64bit

which -a jupyter:
...opt/miniconda3/envs/jlab-test/bin/jupyter
/usr/local/bin/jupyter

pip list:
Package Version
----------------------------- -------------------
anyio 3.1.0
appnope 0.1.2
argon2-cffi 20.1.0
async-generator 1.10
attrs 21.2.0
Babel 2.9.1
backcall 0.2.0
backports.functools-lru-cache 1.6.4
bleach 3.3.0
brotlipy 0.7.0
certifi 2021.5.30
cffi 1.14.5
chardet 4.0.0
cryptography 3.4.7
decorator 5.0.9
defusedxml 0.7.1
entrypoints 0.3
idna 2.10
importlib-metadata 4.4.0
ipykernel 5.5.5
ipython 7.24.1
ipython-genutils 0.2.0
jedi 0.18.0
Jinja2 3.0.1
json5 0.9.5
jsonschema 3.2.0
jupyter-client 6.1.12
jupyter-core 4.7.1
jupyter-server 1.8.0
jupyterlab 3.0.16
jupyterlab-pygments 0.1.2
jupyterlab-server 2.6.0
MarkupSafe 2.0.1
matplotlib-inline 0.1.2
mistune 0.8.4
nbclassic 0.3.1
nbclient 0.5.3
nbconvert 6.0.7
nbformat 5.1.3
nest-asyncio 1.5.1
notebook 6.4.0
packaging 20.9
pandocfilters 1.4.2
parso 0.8.2
pexpect 4.8.0
pickleshare 0.7.5
pip 21.1.2
prometheus-client 0.11.0
prompt-toolkit 3.0.18
ptyprocess 0.7.0
pycparser 2.20
Pygments 2.9.0
pyOpenSSL 20.0.1
pyparsing 2.4.7
pyrsistent 0.17.3
PySocks 1.7.1
python-dateutil 2.8.1
pytz 2021.1
pyzmq 22.1.0
requests 2.25.1
retrolab 0.2.2
Send2Trash 1.5.0
setuptools 49.6.0.post20210108
six 1.16.0
sniffio 1.2.0
terminado 0.10.0
testpath 0.5.0
tornado 6.1
traitlets 5.0.5
urllib3 1.26.5
wcwidth 0.2.5
webencodings 0.5.1
websocket-client 0.57.0
wheel 0.36.2
zipp 3.4.1

conda list:
# packages in environment at ...opt/miniconda3/envs/jlab-test:
#
# Name Version Build Channel
anyio 3.1.0 py39h6e9494a_0 conda-forge
appnope 0.1.2 py39h6e9494a_1 conda-forge
argon2-cffi 20.1.0 py39hcbf5805_2 conda-forge
async_generator 1.10 py_0 conda-forge
attrs 21.2.0 pyhd8ed1ab_0 conda-forge
babel 2.9.1 pyh44b312d_0 conda-forge
backcall 0.2.0 pyh9f0ad1d_0 conda-forge
backports 1.0 py_2 conda-forge
backports.functools_lru_cache 1.6.4 pyhd8ed1ab_0 conda-forge
bleach 3.3.0 pyh44b312d_0 conda-forge
brotlipy 0.7.0 py39hcbf5805_1001 conda-forge
ca-certificates 2021.5.30 h033912b_0 conda-forge
certifi 2021.5.30 py39h6e9494a_0 conda-forge
cffi 1.14.5 py39h319c39b_0 conda-forge
chardet 4.0.0 py39h6e9494a_1 conda-forge
cryptography 3.4.7 py39ha2c9959_0 conda-forge
decorator 5.0.9 pyhd8ed1ab_0 conda-forge
defusedxml 0.7.1 pyhd8ed1ab_0 conda-forge
entrypoints 0.3 pyhd8ed1ab_1003 conda-forge
idna 2.10 pyh9f0ad1d_0 conda-forge
importlib-metadata 4.4.0 py39h6e9494a_0 conda-forge
ipykernel 5.5.5 py39h71a6800_0 conda-forge
ipython 7.24.1 py39h71a6800_0 conda-forge
ipython_genutils 0.2.0 py_1 conda-forge
jedi 0.18.0 py39h6e9494a_2 conda-forge
jinja2 3.0.1 pyhd8ed1ab_0 conda-forge
json5 0.9.5 pyh9f0ad1d_0 conda-forge
jsonschema 3.2.0 pyhd8ed1ab_3 conda-forge
jupyter_client 6.1.12 pyhd8ed1ab_0 conda-forge
jupyter_core 4.7.1 py39h6e9494a_0 conda-forge
jupyter_server 1.8.0 pyhd8ed1ab_0 conda-forge
jupyterlab 3.0.16 pyhd8ed1ab_0 conda-forge
jupyterlab_pygments 0.1.2 pyh9f0ad1d_0 conda-forge
jupyterlab_server 2.6.0 pyhd8ed1ab_0 conda-forge
libcxx 11.1.0 habf9029_0 conda-forge
libffi 3.3 h046ec9c_2 conda-forge
libsodium 1.0.18 hbcb3906_1 conda-forge
markupsafe 2.0.1 py39h89e85a6_0 conda-forge
matplotlib-inline 0.1.2 pyhd8ed1ab_2 conda-forge
mistune 0.8.4 py39hcbf5805_1003 conda-forge
nbclassic 0.3.1 pyhd8ed1ab_1 conda-forge
nbclient 0.5.3 pyhd8ed1ab_0 conda-forge
nbconvert 6.0.7 py39h6e9494a_3 conda-forge
nbformat 5.1.3 pyhd8ed1ab_0 conda-forge
ncurses 6.2 h2e338ed_4 conda-forge
nest-asyncio 1.5.1 pyhd8ed1ab_0 conda-forge
notebook 6.4.0 pyha770c72_0 conda-forge
openssl 1.1.1k h0d85af4_0 conda-forge
packaging 20.9 pyh44b312d_0 conda-forge
pandoc 2.14.0.1 h0d85af4_0 conda-forge
pandocfilters 1.4.2 py_1 conda-forge
parso 0.8.2 pyhd8ed1ab_0 conda-forge
pexpect 4.8.0 pyh9f0ad1d_2 conda-forge
pickleshare 0.7.5 py_1003 conda-forge
pip 21.1.2 pyhd8ed1ab_0 conda-forge
prometheus_client 0.11.0 pyhd8ed1ab_0 conda-forge
prompt-toolkit 3.0.18 pyha770c72_0 conda-forge
ptyprocess 0.7.0 pyhd3deb0d_0 conda-forge
pycparser 2.20 pyh9f0ad1d_2 conda-forge
pygments 2.9.0 pyhd8ed1ab_0 conda-forge
pyopenssl 20.0.1 pyhd8ed1ab_0 conda-forge
pyparsing 2.4.7 pyh9f0ad1d_0 conda-forge
pyrsistent 0.17.3 py39hcbf5805_2 conda-forge
pysocks 1.7.1 py39h6e9494a_3 conda-forge
python 3.9.4 h9133fd0_0_cpython conda-forge
python-dateutil 2.8.1 py_0 conda-forge
python_abi 3.9 1_cp39 conda-forge
pytz 2021.1 pyhd8ed1ab_0 conda-forge
pyzmq 22.1.0 py39h7fec2f1_0 conda-forge
readline 8.1 h05e3726_0 conda-forge
requests 2.25.1 pyhd3deb0d_0 conda-forge
retrolab 0.2.2 pyhd8ed1ab_0 conda-forge
send2trash 1.5.0 py_0 conda-forge
setuptools 49.6.0 py39h6e9494a_3 conda-forge
six 1.16.0 pyh6c4a22f_0 conda-forge
sniffio 1.2.0 py39h6e9494a_1 conda-forge
sqlite 3.35.5 h44b9ce1_0 conda-forge
terminado 0.10.0 py39h6e9494a_0 conda-forge
testpath 0.5.0 pyhd8ed1ab_0 conda-forge
tk 8.6.10 h0419947_1 conda-forge
tornado 6.1 py39hcbf5805_1 conda-forge
traitlets 5.0.5 py_0 conda-forge
tzdata 2021a he74cb21_0 conda-forge
urllib3 1.26.5 pyhd8ed1ab_0 conda-forge
wcwidth 0.2.5 pyh9f0ad1d_2 conda-forge
webencodings 0.5.1 py_1 conda-forge
websocket-client 0.57.0 py39h6e9494a_4 conda-forge
wheel 0.36.2 pyhd3deb0d_0 conda-forge
xz 5.2.5 haf1e3a3_1 conda-forge
zeromq 4.3.4 h1c7c35f_0 conda-forge
zipp 3.4.1 pyhd8ed1ab_0 conda-forge
zlib 1.2.11 h7795811_1010 conda-forge

conda env:
name: jlab-test
channels:
- conda-forge
- defaults
dependencies:
- anyio=3.1.0=py39h6e9494a_0
- appnope=0.1.2=py39h6e9494a_1
- argon2-cffi=20.1.0=py39hcbf5805_2
- async_generator=1.10=py_0
- attrs=21.2.0=pyhd8ed1ab_0
- babel=2.9.1=pyh44b312d_0
- backcall=0.2.0=pyh9f0ad1d_0
- backports=1.0=py_2
- backports.functools_lru_cache=1.6.4=pyhd8ed1ab_0
- bleach=3.3.0=pyh44b312d_0
- brotlipy=0.7.0=py39hcbf5805_1001
- ca-certificates=2021.5.30=h033912b_0
- certifi=2021.5.30=py39h6e9494a_0
- cffi=1.14.5=py39h319c39b_0
- chardet=4.0.0=py39h6e9494a_1
- cryptography=3.4.7=py39ha2c9959_0
- decorator=5.0.9=pyhd8ed1ab_0
- defusedxml=0.7.1=pyhd8ed1ab_0
- entrypoints=0.3=pyhd8ed1ab_1003
- idna=2.10=pyh9f0ad1d_0
- importlib-metadata=4.4.0=py39h6e9494a_0
- ipykernel=5.5.5=py39h71a6800_0
- ipython=7.24.1=py39h71a6800_0
- ipython_genutils=0.2.0=py_1
- jedi=0.18.0=py39h6e9494a_2
- jinja2=3.0.1=pyhd8ed1ab_0
- json5=0.9.5=pyh9f0ad1d_0
- jsonschema=3.2.0=pyhd8ed1ab_3
- jupyter_client=6.1.12=pyhd8ed1ab_0
- jupyter_core=4.7.1=py39h6e9494a_0
- jupyter_server=1.8.0=pyhd8ed1ab_0
- jupyterlab=3.0.16=pyhd8ed1ab_0
- jupyterlab_pygments=0.1.2=pyh9f0ad1d_0
- jupyterlab_server=2.6.0=pyhd8ed1ab_0
- libcxx=11.1.0=habf9029_0
- libffi=3.3=h046ec9c_2
- libsodium=1.0.18=hbcb3906_1
- markupsafe=2.0.1=py39h89e85a6_0
- matplotlib-inline=0.1.2=pyhd8ed1ab_2
- mistune=0.8.4=py39hcbf5805_1003
- nbclassic=0.3.1=pyhd8ed1ab_1
- nbclient=0.5.3=pyhd8ed1ab_0
- nbconvert=6.0.7=py39h6e9494a_3
- nbformat=5.1.3=pyhd8ed1ab_0
- ncurses=6.2=h2e338ed_4
- nest-asyncio=1.5.1=pyhd8ed1ab_0
- notebook=6.4.0=pyha770c72_0
- openssl=1.1.1k=h0d85af4_0
- packaging=20.9=pyh44b312d_0
- pandoc=2.14.0.1=h0d85af4_0
- pandocfilters=1.4.2=py_1
- parso=0.8.2=pyhd8ed1ab_0
- pexpect=4.8.0=pyh9f0ad1d_2
- pickleshare=0.7.5=py_1003
- pip=21.1.2=pyhd8ed1ab_0
- prometheus_client=0.11.0=pyhd8ed1ab_0
- prompt-toolkit=3.0.18=pyha770c72_0
- ptyprocess=0.7.0=pyhd3deb0d_0
- pycparser=2.20=pyh9f0ad1d_2
- pygments=2.9.0=pyhd8ed1ab_0
- pyopenssl=20.0.1=pyhd8ed1ab_0
- pyparsing=2.4.7=pyh9f0ad1d_0
- pyrsistent=0.17.3=py39hcbf5805_2
- pysocks=1.7.1=py39h6e9494a_3
- python=3.9.4=h9133fd0_0_cpython
- python-dateutil=2.8.1=py_0
- python_abi=3.9=1_cp39
- pytz=2021.1=pyhd8ed1ab_0
- pyzmq=22.1.0=py39h7fec2f1_0
- readline=8.1=h05e3726_0
- requests=2.25.1=pyhd3deb0d_0
- retrolab=0.2.2=pyhd8ed1ab_0
- send2trash=1.5.0=py_0
- setuptools=49.6.0=py39h6e9494a_3
- six=1.16.0=pyh6c4a22f_0
- sniffio=1.2.0=py39h6e9494a_1
- sqlite=3.35.5=h44b9ce1_0
- terminado=0.10.0=py39h6e9494a_0
- testpath=0.5.0=pyhd8ed1ab_0
- tk=8.6.10=h0419947_1
- tornado=6.1=py39hcbf5805_1
- traitlets=5.0.5=py_0
- tzdata=2021a=he74cb21_0
- urllib3=1.26.5=pyhd8ed1ab_0
- wcwidth=0.2.5=pyh9f0ad1d_2
- webencodings=0.5.1=py_1
- websocket-client=0.57.0=py39h6e9494a_4
- wheel=0.36.2=pyhd3deb0d_0
- xz=5.2.5=haf1e3a3_1
- zeromq=4.3.4=h1c7c35f_0
- zipp=3.4.1=pyhd8ed1ab_0
- zlib=1.2.11=h7795811_1010
prefix: ...opt/miniconda3/envs/jlab-test

Command Line Output
No output
Browser Output
No output
@Yanay1 Yanay1 added the bug Something isn't working label Jun 4, 2021
@welcome
Copy link

welcome bot commented Jun 4, 2021

Thank you for opening your first issue in this project! Engagement like this is essential for open source projects! 🤗

If you haven't done so already, check out Jupyter's Code of Conduct. Also, please try to follow the issue template as it helps other other community members to contribute more effectively.
welcome
You can meet the other Jovyans by joining our Discourse forum. There is also an intro thread there where you can stop by and say Hi! 👋

Welcome to the Jupyter community! 🎉

@jtpio
Copy link
Member

jtpio commented Jun 4, 2021

Thanks @Yanay1 for the report 👍

@ericvd-ucb
Copy link

@yuvipanda. did you see this one

@yuvipanda
Copy link
Contributor

When I try to open the link in retrolab, it gets me to this URL, as a XHR request:

https://data8.datahub.berkeley.edu/user/yuvipanda/api/contents/hello.bin?content=0&1622823746173

In classic notebook, I instead get:

https://data8.datahub.berkeley.edu/user/yuvipanda/notebooks/hello.bin

@yuvipanda
Copy link
Contributor

External links seem to work fine.

@jtpio
Copy link
Member

jtpio commented Jun 10, 2021

It might be related to this logic in JupyterLab that handles links:

https://github.com/jupyterlab/jupyterlab/blob/716edcafdfce855d29bd8f4a22e3ed44f021b195/packages/rendermime-extension/src/index.ts#L59-L84

In JupyterLab, the code snippet above would open the document in the main area:

handle-link-lab.mp4

In RetroLab the same snippet doesn't do anything when linking to the same document, but open the notebook in a new tab if it is different:

handle-link-retro.mp4

@yuvipanda
Copy link
Contributor

Hmm, right. So to step back, the problem to solve is that we want Python to be able to make links that users can click to download a particular file. I guess with classic or lab it already depends on the kinda file you are downloading - in classic, if the link is to a PNG file, I get an error in the editor...

@jtpio
Copy link
Member

jtpio commented Sep 3, 2021

It might be related to this logic in JupyterLab that handles links:

https://github.com/jupyterlab/jupyterlab/blob/716edcafdfce855d29bd8f4a22e3ed44f021b195/packages/rendermime-extension/src/index.ts#L59-L84

Reading that code, it looks like adding the download attribute to the link element should do the trick.

Testing with that gist and code snippet on Binder:

https://gist.github.com/jtpio/4a6a34da66b32249e28df718ec30e4d7

from IPython.display import display, HTML, Javascript
path = "tour.ipynb"
out_html = """
<p>Click <a download href="{}" target="_blank">here</a>to download the file.</p>
""".format(path)

display(HTML(out_html))

Gives the following, which works RetroLab out of the box:

download-attr.mp4

@yuvipanda @Yanay1 would you be able to check if this solves your issue? Thanks!

@yuvipanda
Copy link
Contributor

I think otter recently added the 'download' link so this should be fixed ucbds-infra/otter-grader#343.

@jtpio
Copy link
Member

jtpio commented Sep 3, 2021

Alright, closing as fixed then. Thanks for checking!

@jtpio jtpio closed this as completed Sep 3, 2021
@jtpio jtpio added this to the Reference milestone Sep 3, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants