Add interactive template with python environment selector
This commit is contained in:
parent
494ba17aaf
commit
dea39b9462
5 changed files with 105 additions and 43 deletions
|
@ -58,6 +58,9 @@ quote-style = "single"
|
|||
inline-quotes = "single"
|
||||
docstring-quotes = "double"
|
||||
|
||||
[tool.ruff.lint.pydocstyle]
|
||||
convention = "numpy"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
|
|
@ -4,8 +4,6 @@ from importlib.metadata import version
|
|||
|
||||
from .spawner import GlicidSpawner
|
||||
|
||||
__all__ = [
|
||||
'GlicidSpawner',
|
||||
]
|
||||
__all__ = ['GlicidSpawner']
|
||||
|
||||
__version__ = version('glicid-spawner')
|
||||
|
|
65
src/glicid_spawner/pyenv.py
Normal file
65
src/glicid_spawner/pyenv.py
Normal file
|
@ -0,0 +1,65 @@
|
|||
"""Python environment module."""
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class PyEnv:
|
||||
"""Python environment generic class."""
|
||||
|
||||
name: str
|
||||
path: str
|
||||
|
||||
def __eq__(self, item):
|
||||
return self.path == str(item)
|
||||
|
||||
|
||||
class UserPyEnv(PyEnv):
|
||||
"""User python environment."""
|
||||
|
||||
scope = 'USER'
|
||||
|
||||
|
||||
class TeamPyEnv(PyEnv):
|
||||
"""Team python environment."""
|
||||
|
||||
scope = 'TEAM'
|
||||
|
||||
|
||||
class GlobalPyEnv(PyEnv):
|
||||
"""Global python environment."""
|
||||
|
||||
scope = 'GLOBAL'
|
||||
|
||||
|
||||
def get_pyenv_user(username: str) -> list:
|
||||
"""List of python environment available to the user."""
|
||||
return [
|
||||
# Dummy values
|
||||
UserPyEnv('base', f'/micromamba/{username}'),
|
||||
UserPyEnv('pytorch', f'/micromamba/{username}/envs/pytorch'),
|
||||
]
|
||||
|
||||
|
||||
def get_pyenv_team() -> list:
|
||||
"""List of python environment available to the user's team."""
|
||||
return [
|
||||
# Dummy values
|
||||
TeamPyEnv(
|
||||
'nuts-workshop', '/micromamba/operator/share/nuts-workshop-team/env/envs/nuts-workshop'
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def get_pyenv_global() -> list:
|
||||
"""List of python environment available globally."""
|
||||
return [
|
||||
# Dummy values
|
||||
GlobalPyEnv('base', '/micromamba/operator/envs/base'),
|
||||
GlobalPyEnv('data-science', '/micromamba/operator/envs/data-science'),
|
||||
]
|
||||
|
||||
|
||||
def get_pyenv(username: str) -> list:
|
||||
"""List of all the python environment available to a user."""
|
||||
return get_pyenv_user() + get_pyenv_team() + get_pyenv_global()
|
|
@ -1,51 +1,28 @@
|
|||
"""GLiCID spawner module."""
|
||||
|
||||
import shlex
|
||||
|
||||
from batchspawner import SlurmSpawner
|
||||
from jinja2 import Environment, PackageLoader, select_autoescape
|
||||
|
||||
from .pyenv import get_pyenv
|
||||
|
||||
|
||||
class GlicidSpawner(SlurmSpawner):
|
||||
"""Glicid SLURM Spawner."""
|
||||
|
||||
def _options_form_default(self):
|
||||
default_env = f'YOURNAME={self.user.name}\n'
|
||||
return f"""
|
||||
<div class="form-group">
|
||||
<label for="args">Extra notebook CLI arguments</label>
|
||||
<input name="args" class="form-control"
|
||||
placeholder="e.g. --debug"></input>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="env">Environment variables (one per line)</label>
|
||||
<textarea class="form-control" name="env">{default_env}</textarea>
|
||||
</div>
|
||||
"""
|
||||
def _options_form_default(self) -> str:
|
||||
"""JupyterHub rendered form template."""
|
||||
environment = Environment(
|
||||
loader=PackageLoader('glicid_spawner'),
|
||||
autoescape=select_autoescape(),
|
||||
)
|
||||
template = environment.get_template('interactive.html')
|
||||
|
||||
def options_from_form(self, formdata):
|
||||
return template.render(
|
||||
username=self.user.name,
|
||||
python_envs=get_pyenv(self.user.name),
|
||||
)
|
||||
|
||||
def options_from_form(self, formdata) -> dict:
|
||||
options = {}
|
||||
options['env'] = env = {}
|
||||
|
||||
env_lines = formdata.get('env', [''])
|
||||
for line in env_lines[0].splitlines():
|
||||
if line:
|
||||
key, value = line.split('=', 1)
|
||||
env[key.strip()] = value.strip()
|
||||
|
||||
arg_s = formdata.get('args', [''])[0].strip()
|
||||
if arg_s:
|
||||
options['argv'] = shlex.split(arg_s)
|
||||
options['pyenv'] = formdata['python-env'][0]
|
||||
return options
|
||||
|
||||
def get_args(self):
|
||||
"""Return arguments to pass to the notebook server"""
|
||||
argv = super().get_args()
|
||||
if self.user_options.get('argv'):
|
||||
argv.extend(self.user_options['argv'])
|
||||
return argv
|
||||
|
||||
def get_env(self):
|
||||
env = super().get_env()
|
||||
if self.user_options.get('env'):
|
||||
env.update(self.user_options['env'])
|
||||
return env
|
||||
|
|
19
src/glicid_spawner/templates/interactive.html
Normal file
19
src/glicid_spawner/templates/interactive.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<div class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label for="username" class="col-sm-3 control-label">Username:</label>
|
||||
<div class="col-sm-9">
|
||||
<input class="form-control" name="username" type="text" placeholder="{{username}}" disabled>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="username" class="col-sm-3 control-label">Python environment:</label>
|
||||
<div class="col-sm-9">
|
||||
<select class="form-control" name="python-env">
|
||||
{%- for pyenv in python_envs -%}
|
||||
<option value="{{pyenv.path}}">{{pyenv.name}} ({{pyenv.scope | upper}})</option>
|
||||
{% endfor -%}
|
||||
</select>
|
||||
<input class="form-control" name="username" type="text" placeholder="{username}" disabled>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Loading…
Add table
Reference in a new issue