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

Voila mode #340

Merged
merged 33 commits into from
Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
900ef45
Voila mode wip
mmarchetti Feb 6, 2023
46f27df
Voila icons
mmarchetti Feb 6, 2023
7ea5946
temporarily use branch of rsconnect-python
mmarchetti Feb 6, 2023
e305bd7
update Pipfile.lock for python 3.8
mmarchetti Feb 7, 2023
5dc7e94
more patient waiting for Jupyter to start
mmarchetti Feb 7, 2023
89146b1
pass through Jupyter logs
mmarchetti Feb 7, 2023
8839a3b
Revert "pass through Jupyter logs"
mmarchetti Feb 7, 2023
e315831
dump Jupyter log
mmarchetti Feb 7, 2023
7678933
re-lock Pipfile.lock
mmarchetti Feb 10, 2023
9384937
remove echo suppression
mmarchetti Feb 10, 2023
2910d00
label jupyter log
mmarchetti Feb 10, 2023
9e226c3
upload logs as artifacts
mmarchetti Feb 10, 2023
f3e73e7
artifact on failure
mmarchetti Feb 10, 2023
40e2d7e
fix temporary rsconnect-python URL
mmarchetti Feb 13, 2023
723786a
fix git url again
mmarchetti Feb 13, 2023
80ee016
fix URL
mmarchetti Feb 13, 2023
97694a1
remove pipenv
mmarchetti Feb 13, 2023
118f61a
Merge branch 'master' into mm-voila
mmarchetti Feb 14, 2023
f4d0e4f
fix notebook path in make run
mmarchetti Feb 14, 2023
1bac0bf
uninstall old plugin before installing
mmarchetti Feb 14, 2023
f2618f8
Merge branch 'mm-voila' of github.com:rstudio/rsconnect-jupyter into …
mmarchetti Feb 14, 2023
ffe77c8
fix notebook dir
mmarchetti Feb 14, 2023
7d00034
add Voila to the docs
mmarchetti Feb 15, 2023
204d9bd
deploy in single file mode
mmarchetti Feb 27, 2023
dedc8f9
disable code cell hiding in Voila mode
mmarchetti Feb 27, 2023
5ded8d4
lint
mmarchetti Feb 28, 2023
3d7402b
rsconnect-python from master branch
mmarchetti Mar 7, 2023
3948150
Merge branch 'master' into mm-voila
mmarchetti Mar 7, 2023
3dc1047
update to rsconnect-python 1.15.0b1
mmarchetti Mar 7, 2023
bc4e9a0
Merge branch 'mm-voila' of github.com:rstudio/rsconnect-jupyter into …
mmarchetti Mar 7, 2023
6706207
add asyncmock
mmarchetti Mar 7, 2023
f2f84da
Merge branch 'master' into mm-voila
mmarchetti Mar 7, 2023
73e517d
import from asyncmock
mmarchetti Mar 7, 2023
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
5 changes: 5 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ jobs:
- run: make -C selenium test-env-up
- run: make -C selenium jupyter-up
- run: make -C selenium test
- uses: actions/upload-artifact@v3
if: failure()
with:
name: selenium-logs
path: '**/*.log'
distributions:
needs: test
runs-on: ubuntu-latest
Expand Down
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ run-local: run
.PHONY: install
install: yarn
pipenv install --dev
$(MAKE) install-latest-rsconnect-python
$(MAKE) version-frontend
pipenv run jupyter nbextension install --symlink --user --py rsconnect_jupyter
pipenv run jupyter nbextension enable --py rsconnect_jupyter
Expand Down
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ traitlets = ">=5.1.1"
nbconvert = ">=5.0"
nbformat = "*"
notebook = ">=6.1.5, <7.0.0"
rsconnect-python = ">=1.7.1"
rsconnect-python = {editable = true, git = "https://github.com/rstudio/rsconnect-python.git", ref = "bcwu-voila" }
six = "*"
# Dependabot fixes
py = ">=1.10.0"
Expand Down
1,775 changes: 976 additions & 799 deletions Pipfile.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions mock_connect.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ def read_html(tarball):
app_modes = {
"static": 4,
"jupyter-static": 7,
"jupyter-voila": 16,
}


Expand Down
21 changes: 20 additions & 1 deletion rsconnect_jupyter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import sys

from six.moves.urllib.parse import unquote_plus
from os.path import dirname
from os.path import basename, dirname

from notebook.base.handlers import APIHandler
from notebook.utils import url_path_join
Expand All @@ -22,6 +22,7 @@
from rsconnect.bundle import (
make_notebook_html_bundle,
make_notebook_source_bundle,
make_voila_bundle,
write_manifest,
)
from rsconnect.environment import Environment
Expand Down Expand Up @@ -193,6 +194,24 @@ def post(self, action):
except Exception as exc:
self.log.exception("Bundle creation failed")
raise web.HTTPError(500, "Bundle creation failed: %s" % exc)
elif app_mode == "jupyter-voila":
# workaround current dir issue with rsconnect-python's voila deployments
os.chdir(dirname(os_path))
if not environment_dict:
raise web.HTTPError(400, "environment is required for jupyter-voila app_mode")

try:
bundle = make_voila_bundle(
dirname(os_path),
basename(os_path),
extra_files,
[], # excludes
False, # force_generate
Environment(**environment_dict),
)
except Exception as exc:
self.log.exception("Bundle creation failed")
raise web.HTTPError(500, "Bundle creation failed: %s" % exc)
else:
raise web.HTTPError(
400,
Expand Down
18 changes: 14 additions & 4 deletions rsconnect_jupyter/static/connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,7 @@ define([
* @param userEditedTitle {String} title as edited by user
* @param selectedDeployLocation {DeploymentLocation.Canceled|DeploymentLocation.New|String} whether this is a new
* deployment, a canceled deployment, or has an app id
* @param selectedAppMode {'jupyter-static'|'static'|null} App mode
* @param selectedAppMode {'jupyter-static'|'static'|'jupyter-voila'|null} App mode
* @param environmentOptions {null|"use-existing-conda"|"use-existing-pip"|"generate-new-pip"|"generate-new-conda"}
* Selected environment option
*/
Expand Down Expand Up @@ -1014,7 +1014,7 @@ define([
}

function updateCheckboxStates() {
var publishingWithSource = (appMode === 'jupyter-static');
var publishingWithSource = (appMode === 'jupyter-static' || appMode === 'jupyter-voila');
var serverSelected = !!selectedEntryId;
var $filesBox = $('#include-files');
var includingFiles = $filesBox.prop('checked');
Expand Down Expand Up @@ -1064,6 +1064,13 @@ define([
' <span class="rsc-label">Publish document with source code</span><br/>',
' <span class="rsc-text-light">Choose this option if you want to create a scheduled report or rebuild your document on the server</span>',
' </a>',
' <a href="#" id="rsc-publish-voila" class="list-group-item rsc-appmode" data-appmode="jupyter-voila">',
' <img src="' +
Jupyter.notebook.base_url +
'nbextensions/rsconnect_jupyter/images/publishDocVoila.png" class="rsc-image">',
' <span class="rsc-label">Publish interactive Voila document with source code</span><br/>',
' <span class="rsc-text-light">Choose this option if you want to publish an interactive notebook with widgets</span>',
' </a>',
' <a href="#" id="rsc-publish-without-source" class="list-group-item rsc-appmode" data-appmode="static">',
' <img src="' +
Jupyter.notebook.base_url +
Expand Down Expand Up @@ -1121,6 +1128,7 @@ define([
var hasEnvironmentYml = false;
var isCondaEnvironment = false;

publishModal.css('overflow-y', 'auto');
publishModal.find('#version-info').html(
'rsconnect-jupyter server extension version: ' +
rsconnectVersionInfo.rsconnect_jupyter_server_extension + '<br />' +
Expand Down Expand Up @@ -1677,7 +1685,7 @@ define([
* @param serverId {String} Server Unique Identifier
* @param title {String} App title
* @param appId {Number} App ID
* @param appMode {'static'|'jupyter-static'} App mode
* @param appMode {'static'|'jupyter-static'|'jupyter-voila'} App mode
* @param files {Array<String>} list of file paths that will be included
* @param environmentOptions {null|"use-existing-conda"|"use-existing-pip"|"generate-new"}
* What the selected environment options are
Expand All @@ -1696,6 +1704,8 @@ define([
return '[document]';
} else if (mode === 'jupyter-static' || mode === 7) {
return '[document with source code]';
} else if (mode === 'jupyter-voila' || mode === 16) {
return '[interactive Voila document with source code]';
} else {
return '[unknown type]';
}
Expand Down Expand Up @@ -1734,7 +1744,7 @@ define([
return div;
}
var newLocationRadio = $(
'<div class="radio"><label><input type="radio" name="location" value="new"><span id="new-location"</span></label></div>'
'<div class="radio"><label><input data-appmode="' + appMode + '" type="radio" name="location" value="new"><span id="new-location"</span></label></div>'
);

var divider = $('<p>Or update:</p>');
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions rsconnect_jupyter/static/rsconnect.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ define([
* @param serverId {string} the server identifier
* @param appId {number} the numeric app ID
* @param notebookTitle {string} Title of the notebook to be passed as name/title
* @param appMode {'static'|'jupyter-static'} App mode to deploy. 'static' is not rendered.
* @param appMode {'static'|'jupyter-static'|'jupyter-voila'} App mode to deploy. 'static' is not rendered.
* @param files {Array<String>} paths to files to deploy.
* @param condaMode {boolean} whether or not to use conda to build an `environment.yml`.
* @param forceGenerate {boolean} whether to force `requirements.txt` to be generated even if one exists.
Expand Down Expand Up @@ -477,7 +477,7 @@ define([
return xhr;
}

if (appMode === 'jupyter-static') {
if (appMode === 'jupyter-static' || appMode === 'jupyter-voila') {
return this.inspectEnvironment(condaMode, forceGenerate).then(deploy);
} else {
return deploy(null);
Expand Down
31 changes: 16 additions & 15 deletions selenium/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,14 @@ prepare-logging:
tee ${PYTESTLOG} < ${TMP_PIPE} &

run: $(NOTEBOOKS_DIR)
@${DOCKER_RUN_COMMAND} ${COMMAND}
${DOCKER_RUN_COMMAND} ${COMMAND}

test-env-up: grid-up connect-up

test-env-down: network-down

wait-for-systems-up:
@docker run --rm \
docker run --rm \
--name=systemstat \
--network=$(NETWORK) \
--volume=${CURDIR}/..:${RSCONNECT_DIR} \
Expand All @@ -140,7 +140,8 @@ wait-for-systems-up:
-n $$(( ${SCALE_FIREFOX} + ${SCALE_CHROME} )) \
-l ${LOGS_DIR} \
-j '${JUPYTER_SCHEME}://${JUPYTER_HOST}:${JUPYTER_PORT}' \
-c '${CONNECT_SCHEME}://${CONNECT_HOST}:${CONNECT_PORT}'
-c '${CONNECT_SCHEME}://${CONNECT_HOST}:${CONNECT_PORT}' \
|| (echo "Jupyter log: "; cat ${JUPYTER_LOG})

grid-up: network-up
NETWORK=${NETWORK} \
Expand All @@ -162,14 +163,14 @@ grid-restart:

network-up:
$(eval NETWORK_EXISTS=$(shell docker network inspect ${NETWORK} > /dev/null 2>&1 && echo 0 || echo 1))
@if [ "${NETWORK_EXISTS}" = "1" ] ; then \
if [ "${NETWORK_EXISTS}" = "1" ] ; then \
echo "Creating network: ${NETWORK}"; \
docker network create --driver bridge ${NETWORK} ; \
fi

network-down: connect-down grid-down
$(eval NETWORK_EXISTS=$(shell docker network inspect ${NETWORK} > /dev/null 2>&1 && echo 0 || echo 1))
@if [ "${NETWORK_EXISTS}" = "0" ] ; then \
if [ "${NETWORK_EXISTS}" = "0" ] ; then \
for i in `docker network inspect -f '{{range .Containers}}{{.Name}} {{end}}' ${NETWORK}`; do \
echo "Removing container \"$${i}\" from network \"${NETWORK}\""; \
docker network disconnect -f ${NETWORK} $${i}; \
Expand All @@ -179,8 +180,8 @@ network-down: connect-down grid-down
fi

jupyter-up: $(NOTEBOOKS_DIR)
@echo "Creating ${JUPYTER_HOST} ..."
@docker run --rm -d --init \
echo "Creating ${JUPYTER_HOST} ..."
docker run --rm -d --init \
${DOCKER_TTY_FLAGS} \
--name=${JUPYTER_HOST} \
--network=${NETWORK} \
Expand All @@ -197,20 +198,20 @@ jupyter-up: $(NOTEBOOKS_DIR)
$(JUPYTER_IMAGE) \
make -C ${RSCONNECT_DIR} run JUPYTER_LOG_LEVEL=$(JUPYTER_LOG_LEVEL) \
1>/dev/null
@docker logs -f ${JUPYTER_HOST} > ${JUPYTER_LOG} &
@echo " done"
docker logs -f ${JUPYTER_HOST} > ${JUPYTER_LOG} &
echo " done"

jupyter-down:
$(eval JUPYTER_EXISTS=$(shell docker container inspect ${JUPYTER_HOST} > /dev/null 2>&1 && echo 0 || echo 1))
@if [ "${JUPYTER_EXISTS}" = "0" ] ; then \
if [ "${JUPYTER_EXISTS}" = "0" ] ; then \
echo "Stopping ${JUPYTER_HOST} ..."; \
docker stop ${JUPYTER_HOST} 1>/dev/null; \
echo " done"; \
fi

connect-up:
@echo "Creating ${CONNECT_HOST} ..."
@docker run --rm -d --init \
echo "Creating ${CONNECT_HOST} ..."
docker run --rm -d --init \
${DOCKER_TTY_FLAGS} \
--name=${CONNECT_HOST} \
--network=${NETWORK} \
Expand All @@ -222,12 +223,12 @@ connect-up:
$(CONNECT_IMAGE) \
flask run --host=0.0.0.0 --port=${CONNECT_PORT} \
1>/dev/null
@docker logs -f ${CONNECT_HOST} > ${CONNECT_LOG} &
@echo " done"
docker logs -f ${CONNECT_HOST} > ${CONNECT_LOG} &
echo " done"

connect-down:
$(eval CONNECT_EXISTS=$(shell docker container inspect ${CONNECT_HOST} > /dev/null 2>&1 && echo 0 || echo 1))
@if [ "${CONNECT_EXISTS}" = "0" ] ; then \
if [ "${CONNECT_EXISTS}" = "0" ] ; then \
echo "Stopping ${CONNECT_HOST} ..."; \
docker stop ${CONNECT_HOST} 1>/dev/null; \
echo " done"; \
Expand Down
2 changes: 1 addition & 1 deletion selenium/tools/systemstat/sutstat.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


class SutStat(systemstat.SystemStat):
def __init__(self, url="http://localhost:6969", sleep=5.0, wait=60, **kwargs):
def __init__(self, url="http://localhost:6969", sleep=5.0, wait=120, **kwargs):
super(SutStat, self).__init__(sleep=sleep, wait=wait, **kwargs)

self._url = url
Expand Down