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

Add support of configuring extension logic using env. variables #86

Open
wants to merge 3 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
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# jupyter-rsession-proxy

**jupyter-rsession-proxy** provides Jupyter server and notebook extensions to proxy RStudio.
[![PyPI](https://img.shields.io/pypi/v/jupyter-rsession-proxy?label=PyPI%20Version)](https://pypi.org/project/jupyter-rsession-proxy/)
[![PyPI - Wheel](https://img.shields.io/pypi/wheel/jupyter-rsession-proxy)](https://pypi.org/project/jupyter-rsession-proxy/)

**jupyter-rsession-proxy** provides Jupyter server and notebook extensions to proxy RStudio Server (multi-user env.) or RStudio Session (single-user env.).

![Screenshot](screenshot.png)

Expand All @@ -25,6 +28,20 @@ Install the library:
pip install jupyter-rsession-proxy
```

## Configuring using environment variables

This extension can be configured using environment variables.
Below is a list with all supported environment variables.

| Environment variable | Description |
| --------------------- |-------------|
| RSTUDIO_RSERVER_BIN | Prioritized location for searching binary file "rserver". Should be an absolute path to rserver or not set. |
| RSTUDIO_RSERVER_ARGS | Overrides all arguments (except --www-port) for "rserver" binary. |
| RSTUDIO_RSESSION_BIN | Prioritized location for searching binary file "rsession". Should be an absolute path to rserver or not set. |
| RSTUDIO_RSESSION_ARGS | Overrides all arguments (except --www-port and --user-identity) for "rsession" binary. |
| RSTUDIO_FOLDER | Prioritized folder for searching all RStudio related binary files. Should be an absolute path to folder or not set. |


## Example

[rocker/binder](https://hub.docker.com/r/rocker/binder) contains an example installation which you can run on binder.
Expand Down
70 changes: 57 additions & 13 deletions jupyter_rsession_proxy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,50 +1,94 @@
import os
import subprocess
"""
This file contains logic that is required for "jupyter-server-proxy" to register additional launchers in Jupyter Notebook.
Docs: https://github.com/jupyterhub/jupyter-server-proxy/blob/master/docs/server-process.rst
"""
import getpass
import os
import shlex
import shutil
import subprocess


# RSTUDIO_RSERVER_BIN - Prioritized location for searching binary file "rserver".
# Should be an absolute path to rserver or not set.
RSTUDIO_RSERVER_BIN = os.getenv('RSTUDIO_RSERVER_BIN')

# RSTUDIO_RSERVER_ARGS - Overrides all arguments (except --www-port) for "rserver" binary.
# Should be an absolute path to rserver or not set.
RSTUDIO_RSERVER_ARGS = os.getenv('RSTUDIO_RSERVER_ARGS', '')

# RSTUDIO_RSESSION_BIN - Prioritized location for searching binary file "rsession".
RSTUDIO_RSESSION_BIN = os.getenv('RSTUDIO_RSESSION_BIN')

# RSTUDIO_RSESSION_ARGS - Overrides all arguments (except --www-port and --user-identity) for "rsession" binary.
RSTUDIO_RSESSION_ARGS = os.getenv(
'RSTUDIO_RSESSION_ARGS',
'--standalone=1 --program-mode=server --log-stderr=1 --session-timeout-minutes=0'
)

# RSTUDIO_FOLDER - Prioritized folder for searching all RStudio related binary files.
# Should be an absolute path to folder or not set.
RSTUDIO_FOLDER = os.getenv('RSTUDIO_FOLDER')


def get_rstudio_executable(prog):
"""Find location (absolute path) of RStudio program"""
# Try env. variable RSTUDIO_FOLDER to search prog in
if RSTUDIO_FOLDER:
bin_location = os.path.join(RSTUDIO_FOLDER, prog)
if os.path.exists(bin_location):
return bin_location

# Find prog in known locations
other_paths = [
# When rstudio-server deb is installed
os.path.join('/usr/lib/rstudio-server/bin', prog),
# When just rstudio deb is installed
os.path.join('/usr/lib/rstudio/bin', prog),
]

# Try to find prog in PATH
if shutil.which(prog):
return prog

for op in other_paths:
if os.path.exists(op):
return op

raise FileNotFoundError(f'Could not find {prog} in PATH')
raise FileNotFoundError(f'Could not find {prog} in PATH or well known locations')

def get_icon_path():
"""Get path to icon for Jupyter web interface"""
return os.path.join(
os.path.dirname(os.path.abspath(__file__)), 'icons', 'rstudio.svg'
)

def setup_rserver():
"""Get entry for RServer"""
def _get_env(port):
return dict(USER=getpass.getuser())

def _get_cmd(port):
return [
get_rstudio_executable('rserver'),
bin_file = RSTUDIO_RSERVER_BIN if RSTUDIO_RSERVER_BIN else get_rstudio_executable('rserver')
cmd = [
bin_file,
'--www-port=' + str(port)
]
if RSTUDIO_RSERVER_ARGS:
cmd.extend(shlex.split(RSTUDIO_RSERVER_ARGS))
return cmd

return {
'command': _get_cmd,
'environment': _get_env,
'launcher_entry': {
'title': 'RStudio',
'title': 'RStudio Server',
'icon_path': get_icon_path()
}
}

def setup_rsession():
"""Get entry for RSession"""
def _get_env(port):
# Detect various environment variables rsession requires to run
# Via rstudio's src/cpp/core/r_util/REnvironmentPosix.cpp
Expand All @@ -65,21 +109,21 @@ def _get_env(port):
}

def _get_cmd(port):
return [
get_rstudio_executable('rsession'),
'--standalone=1',
'--program-mode=server',
'--log-stderr=1',
'--session-timeout-minutes=0',
bin_file = RSTUDIO_RSESSION_BIN if RSTUDIO_RSESSION_BIN else get_rstudio_executable('rsession')
cmd = [
bin_file,
'--user-identity=' + getpass.getuser(),
'--www-port=' + str(port)
]
if RSTUDIO_RSESSION_ARGS:
cmd.extend(shlex.split(RSTUDIO_RSESSION_ARGS))
return cmd

return {
'command': _get_cmd,
'environment': _get_env,
'launcher_entry': {
'title': 'RStudio',
'title': 'RStudio Session',
'icon_path': get_icon_path()
}
}
20 changes: 12 additions & 8 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import setuptools

setuptools.setup(
name="jupyter-rsession-proxy",
version='1.1',
url="https://github.com/jupyterhub/jupyter-rsession-proxy",
author="Ryan Lovett & Yuvi Panda",
description="Jupyter extension to proxy RStudio",
name='jupyter-rsession-proxy',
version='1.2',
url='https://github.com/jupyterhub/jupyter-rsession-proxy',
author='Ryan Lovett & Yuvi Panda & Kirill Makhonin',
description='Jupyter extension to proxy RStudio',
packages=setuptools.find_packages(),
keywords=['Jupyter'],
classifiers=['Framework :: Jupyter'],
keywords=['Jupyter'],
classifiers=[
'Framework :: Jupyter',
'Programming Language :: Python :: 3'
],
install_requires=[
'jupyter-server-proxy'
],
entry_points={
'jupyter_serverproxy_servers': [
'rstudio = jupyter_rsession_proxy:setup_rserver'
'rstudio = jupyter_rsession_proxy:setup_rserver',
'rsession = jupyter_rsession_proxy:setup_rsession'
]
},
package_data={
Expand Down