Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Google Colab and Mineo #1056

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
14 changes: 14 additions & 0 deletions nbviewer/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ class NBViewer(Application):
{
"base-url": "NBViewer.base_url",
"binder-base-url": "NBViewer.binder_base_url",
"colab-base-url": "NBViewer.colab_base_url",
"mineo-base-url": "NBViewer.mineo_base_url",
"cache-expiry-max": "NBViewer.cache_expiry_max",
"cache-expiry-min": "NBViewer.cache_expiry_min",
"config-file": "NBViewer.config_file",
Expand Down Expand Up @@ -221,6 +223,16 @@ class NBViewer(Application):
help="URL base for binder notebook execution service.",
).tag(config=True)

colab_base_url = Unicode(
default_value="https://colab.research.google.com",
help="URL base for colab notebook execution service.",
).tag(config=True)

mineo_base_url = Unicode(
default_value="https://b.mineo.app",
help="URL base for mineo notebook execution service.",
).tag(config=True)

cache_expiry_max = Int(
default_value=2 * 60 * 60, help="Maximum cache expiry (seconds)."
).tag(config=True)
Expand Down Expand Up @@ -662,6 +674,8 @@ def init_tornado_application(self):
allow_remote_access=True,
base_url=self._base_url,
binder_base_url=self.binder_base_url,
colab_base_url=self.colab_base_url,
mineo_base_url=self.mineo_base_url,
cache=self.cache,
cache_expiry_max=self.cache_expiry_max,
cache_expiry_min=self.cache_expiry_min,
Expand Down
17 changes: 17 additions & 0 deletions nbviewer/providers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,14 @@ def base_url(self):
def binder_base_url(self):
return self.settings["binder_base_url"]

@property
def colab_base_url(self):
return self.settings["colab_base_url"]

@property
def mineo_base_url(self):
return self.settings["mineo_base_url"]

@property
def cache(self):
return self.settings["cache"]
Expand Down Expand Up @@ -664,11 +672,20 @@ def deliver_notebook(self, **kwargs):
def render_notebook_template(
self, body, nb, download_url, json_notebook, **namespace
):
executor_mineo_url = (
"{mineo_base_url}/import/{notebook_url}".format(
mineo_base_url=self.mineo_base_url, notebook_url=download_url
)
if self.mineo_base_url
else None
)

return self.render_template(
"formats/%s.html" % self.format,
body=body,
nb=nb,
download_url=download_url,
executor_mineo_url=executor_mineo_url,
format=self.format,
default_format=self.default_format,
format_prefix=format_prefix,
Expand Down
49 changes: 39 additions & 10 deletions nbviewer/providers/github/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,18 @@ class GithubClientMixin:
PROVIDER_CTX = {
"provider_label": "GitHub",
"provider_icon": "github",
"executor_label": "Binder",
"executor_icon": "icon-binder",
"executor_label_binder": "Binder",
"executor_icon_binder": "icon-binder",
"executor_label_colab": "Colab",
"executor_icon_colab": "icon-colab",
}

BINDER_TMPL = "{binder_base_url}/gh/{org}/{repo}/{ref}"
BINDER_PATH_TMPL = BINDER_TMPL + "?filepath={path}"

COLAB_TMPL = "{colab_base_url}/github/{org}/{repo}/blob/{ref}"
COLAB_PATH_TMPL = COLAB_TMPL + "/{path}"

@property
def github_url(self):
if getattr(self, "_github_url", None) is None:
Expand Down Expand Up @@ -169,16 +174,19 @@ def render_treelist_template(
path,
branches,
tags,
executor_url,
executor_url_binder,
executor_url_colab,
**namespace,
):
"""
breadcrumbs: list of dict
Breadcrumb 'name' and 'url' to render as links at the top of the notebook page
provider_url: str
URL to the notebook document upstream at the provider (e.g., GitHub)
executor_url: str, optional
URL to execute the notebook document (e.g., Binder)
executor_url_binder: str, optional
URL to execute the notebook document with Binder
executor_url_colab: str, optional
URL to execute the notebook document withe Colab
"""
return self.render_template(
"treelist.html",
Expand All @@ -193,7 +201,8 @@ def render_treelist_template(
tags=tags,
tree_type="github",
tree_label="repositories",
executor_url=executor_url,
executor_url_binder=executor_url_binder,
executor_url_colab=executor_url_colab,
**self.PROVIDER_CTX,
**namespace,
)
Expand Down Expand Up @@ -308,13 +317,20 @@ async def get(self, user: str, repo: str, ref: str, path: str):
entries.extend(others)

# Enable a binder navbar icon if a binder base URL is configured
executor_url = (
executor_url_binder = (
self.BINDER_TMPL.format(
binder_base_url=self.binder_base_url, org=user, repo=repo, ref=ref
)
if self.binder_base_url
else None
)
executor_url_colab = (
self.COLAB_PATH_TMPL.format(
colab_base_url=self.colab_base_url, org=user, repo=repo, ref=ref
)
if self.colab_base_url
else None
)

html = self.render_treelist_template(
entries=entries,
Expand All @@ -326,7 +342,8 @@ async def get(self, user: str, repo: str, ref: str, path: str):
path=path,
branches=branches,
tags=tags,
executor_url=executor_url,
executor_url_binder=executor_url_binder,
executor_url_colab=executor_url_colab,
)
await self.cache_and_finish(html)

Expand Down Expand Up @@ -414,7 +431,7 @@ async def deliver_notebook(
breadcrumbs.extend(self.breadcrumbs(dir_path, base_url))

# Enable a binder navbar icon if a binder base URL is configured
executor_url = (
executor_url_binder = (
self.BINDER_PATH_TMPL.format(
binder_base_url=self.binder_base_url,
org=user,
Expand All @@ -425,6 +442,17 @@ async def deliver_notebook(
if self.binder_base_url
else None
)
executor_url_colab = (
self.COLAB_PATH_TMPL.format(
colab_base_url=self.colab_base_url,
org=user,
repo=repo,
ref=ref,
path=quote(path),
)
if self.binder_base_url
else None
)

try:
# filedata may be bytes, but we need text
Expand All @@ -447,7 +475,8 @@ async def deliver_notebook(
nbjson,
raw_url,
provider_url=blob_url,
executor_url=executor_url,
executor_url_binder=executor_url_binder,
executor_url_colab=executor_url_colab,
breadcrumbs=breadcrumbs,
msg="file from GitHub: %s" % raw_url,
public=True,
Expand Down
Binary file added nbviewer/static/img/icon-colab-color.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added nbviewer/static/img/icon-colab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added nbviewer/static/img/icon-mineo-color.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added nbviewer/static/img/icon-mineo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions nbviewer/static/less/layout.less
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,33 @@ td.page_links {
background-image: url(../img/icon-binder-color.png);
}
}

// colab icon
.fa-icon-colab {
width: 24px;
height: 24px;
margin-top: -8px;
background-image: url(../img/icon-colab.png);
background-repeat: no-repeat;
background-position: center right;
background-size: 24px;
&:hover, &.active {
&:extend(.fa-icon-colab);
background-image: url(../img/icon-colab-color.png);
}
}

// mineo icon
.fa-icon-mineo {
width: 24px;
height: 24px;
margin-top: -8px;
background-image: url(../img/icon-mineo.png);
background-repeat: no-repeat;
background-position: center right;
background-size: 24px;
&:hover, &.active {
&:extend(.fa-icon-mineo);
background-image: url(../img/icon-mineo-color.png);
}
}
11 changes: 10 additions & 1 deletion nbviewer/templates/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,16 @@ saved in a notebook document as a web page.
[mybinder.org](https://mybinder.org/) is a separate web service that lets you
open notebooks in an executable environment, making your code
immediately reproducible by anyone, anywhere. nbviewer shows an *Execute on
Binder* icon in its navbar which
Binder* icon in its navbar

[Google Colab](https://colab.research.google.com/) offers a cloud environment
for editing, running, and sharing notebooks. nbviewer includes an
*Execute on Colab* icon in its navbar.

[mneo.app](https://mineo.app/) is another cloud platform for running and sharing
notebooks with Code, No-code & AI capabilities.
nbviewer features an *Execute on Mineo* icon in its navbar.


## Why does the Execute on Binder button not appear for a notebook?

Expand Down
10 changes: 8 additions & 2 deletions nbviewer/templates/notebook.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,16 @@
{{ layout.head_icon(provider_url, "View on " + provider_label, provider_icon) }}
{% endif %}

{% if executor_url %}
{{ layout.head_icon(executor_url, "Execute on " + executor_label, executor_icon) }}
{% if executor_url_binder %}
{{ layout.head_icon(executor_url_binder, "Execute on " + executor_label_binder, executor_icon_binder) }}
{% endif %}

{% if executor_url_colab %}
{{ layout.head_icon(executor_url_colab, "Execute on " + executor_label_colab, executor_icon_colab) }}
{% endif %}

{{ head_icon(executor_mineo_url, "Execute on MINEO", "icon-mineo") }}

{{ layout.head_icon(download_url, "Download Notebook", "download", True) }}
{% endblock %}

Expand Down
2 changes: 2 additions & 0 deletions nbviewer/tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ def test_generate_config():
assert "NBViewer.base_url" in cfg_text
assert "NBViewer._base_url" not in cfg_text # This shouldn't be configurable
assert "NBViewer.binder_base_url" in cfg_text
assert "NBViewer.colab_base_url" in cfg_text
assert "NBViewer.mineo_base_url" in cfg_text
assert "NBViewer.cache_expiry_max" in cfg_text
assert "NBViewer.cache_expiry_min" in cfg_text
assert "NBViewer.client" in cfg_text
Expand Down