mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-14 13:33:00 +00:00
options_form is a regular configurable
now that we can assume User.spawner exists at all times
This commit is contained in:
@@ -452,12 +452,12 @@ class UserSpawnHandler(BaseHandler):
|
||||
# spawn has supposedly finished, check on the status
|
||||
status = yield current_user.spawner.poll()
|
||||
if status is not None:
|
||||
if self.spawner_class.options_form:
|
||||
if current_user.spawner.options_form:
|
||||
self.redirect(url_path_join(self.hub.server.base_url, 'spawn'))
|
||||
else:
|
||||
yield self.spawn_single_user(current_user)
|
||||
else:
|
||||
if self.spawner_class.options_form:
|
||||
if current_user.spawner.options_form:
|
||||
self.redirect(url_path_join(self.hub.server.base_url, 'spawn'))
|
||||
else:
|
||||
yield self.spawn_single_user(current_user)
|
||||
|
@@ -68,7 +68,7 @@ class LoginHandler(BaseHandler):
|
||||
if user.spawner:
|
||||
status = yield user.spawner.poll()
|
||||
already_running = (status == None)
|
||||
if not already_running and not self.spawner_class.options_form:
|
||||
if not already_running and not user.spawner.options_form:
|
||||
yield self.spawn_single_user(user)
|
||||
self.set_login_cookie(user)
|
||||
next_url = self.get_argument('next', default='')
|
||||
|
@@ -63,10 +63,10 @@ class SpawnHandler(BaseHandler):
|
||||
self.log.debug("User is running: %s", url)
|
||||
self.redirect(url)
|
||||
return
|
||||
if self.spawner_class.options_form:
|
||||
if user.spawner.options_form:
|
||||
html = self.render_template('spawn.html',
|
||||
user=self.get_current_user(),
|
||||
spawner_options_form=self.spawner_class.options_form,
|
||||
spawner_options_form=user.spawner.options_form,
|
||||
)
|
||||
self.finish(html)
|
||||
else:
|
||||
@@ -87,7 +87,7 @@ class SpawnHandler(BaseHandler):
|
||||
form_options = {}
|
||||
for key, byte_list in self.request.body_arguments.items():
|
||||
form_options[key] = [ bs.decode('utf8') for bs in byte_list ]
|
||||
options = self.spawner_class.options_from_form(form_options)
|
||||
options = user.spawner.options_from_form(form_options)
|
||||
yield self.spawn_single_user(user, options=options)
|
||||
url = user.server.base_url
|
||||
self.redirect(url)
|
||||
|
@@ -73,24 +73,33 @@ class Spawner(LoggingConfigurable):
|
||||
help="Enable debug-logging of the single-user server"
|
||||
)
|
||||
|
||||
# options_form is a class attribute, defining an HTML form snippet,
|
||||
# which can be used to specify whether
|
||||
# (i.e. just the <input> elements, not submit button or the <form> tag).
|
||||
# This is **not** a configurable,
|
||||
options_form = ""
|
||||
@classmethod
|
||||
def options_from_form(cls, form_data):
|
||||
options_form = Unicode("", config=True, help="""
|
||||
An HTML form for options a user can specify on launching their server.
|
||||
The surrounding `<form>` element and the submit button are already provided.
|
||||
|
||||
For example:
|
||||
|
||||
Set your key:
|
||||
<input name="key" val="default_key"></input>
|
||||
<br>
|
||||
Choose a letter:
|
||||
<select name="letter" multiple="true">
|
||||
<option value="A">The letter A</option>
|
||||
<option value="B">The letter B</option>
|
||||
</select>
|
||||
""")
|
||||
|
||||
def options_from_form(self, form_data):
|
||||
"""Interpret HTTP form data
|
||||
|
||||
Form data will always arrive as a dict of lists of strings.
|
||||
Override this function to understand single-values, numbers, etc.
|
||||
|
||||
This should coerce form data into the structure expected by self.options,
|
||||
This should coerce form data into the structure expected by self.user_options,
|
||||
which must be a dict.
|
||||
|
||||
Instances will receive this data on self.user_options, after passing through this function.
|
||||
|
||||
This must be a @classmethod.
|
||||
Instances will receive this data on self.user_options, after passing through this function,
|
||||
prior to `Spawner.start`.
|
||||
"""
|
||||
return form_data
|
||||
|
||||
|
@@ -76,8 +76,7 @@ class NeverSpawner(MockSpawner):
|
||||
class FormSpawner(MockSpawner):
|
||||
options_form = "IMAFORM"
|
||||
|
||||
@classmethod
|
||||
def options_from_form(cls, form_data):
|
||||
def options_from_form(self, form_data):
|
||||
options = {}
|
||||
options['notspecified'] = 5
|
||||
if 'bounds' in form_data:
|
||||
|
@@ -65,14 +65,14 @@ def test_spawn_redirect(app):
|
||||
assert r.url.endswith('/wash')
|
||||
|
||||
def test_spawn_page(app):
|
||||
with mock.patch.dict(app.tornado_application.settings, {'spawner_class': FormSpawner}):
|
||||
with mock.patch.dict(app.users.settings, {'spawner_class': FormSpawner}):
|
||||
cookies = app.login_user('jones')
|
||||
r = get_page('spawn', app, cookies=cookies)
|
||||
assert r.url.endswith('/spawn')
|
||||
assert FormSpawner.options_form in r.text
|
||||
|
||||
def test_spawn_form(app, io_loop):
|
||||
with mock.patch.dict(app.tornado_application.settings, {'spawner_class': FormSpawner}):
|
||||
with mock.patch.dict(app.users.settings, {'spawner_class': FormSpawner}):
|
||||
base_url = ujoin(app.proxy.public_server.host, app.hub.server.base_url)
|
||||
cookies = app.login_user('jones')
|
||||
orm_u = orm.User.find(app.db, 'jones')
|
||||
|
Reference in New Issue
Block a user