mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-18 15:33:02 +00:00
@@ -1625,10 +1625,7 @@ class JupyterHub(Application):
|
|||||||
if not self.io_loop:
|
if not self.io_loop:
|
||||||
return
|
return
|
||||||
if self.http_server:
|
if self.http_server:
|
||||||
if self.io_loop._running:
|
self.http_server.stop()
|
||||||
self.io_loop.add_callback(self.http_server.stop)
|
|
||||||
else:
|
|
||||||
self.http_server.stop()
|
|
||||||
self.io_loop.add_callback(self.io_loop.stop)
|
self.io_loop.add_callback(self.io_loop.stop)
|
||||||
|
|
||||||
@gen.coroutine
|
@gen.coroutine
|
||||||
|
@@ -778,7 +778,14 @@ class HubAuthenticated(object):
|
|||||||
except UserNotAllowed as e:
|
except UserNotAllowed as e:
|
||||||
# cache None, in case get_user is called again while processing the error
|
# cache None, in case get_user is called again while processing the error
|
||||||
self._hub_auth_user_cache = None
|
self._hub_auth_user_cache = None
|
||||||
raise HTTPError(403, "{kind} {name} is not allowed.".format(**e.model))
|
# Override redirect so if/when tornado @web.authenticated
|
||||||
|
# tries to redirect to login URL, 403 will be raised instead.
|
||||||
|
# This is not the best, but avoids problems that can be caused
|
||||||
|
# when get_current_user is allowed to raise.
|
||||||
|
def raise_on_redirect(*args, **kwargs):
|
||||||
|
raise HTTPError(403, "{kind} {name} is not allowed.".format(**user_model))
|
||||||
|
self.redirect = raise_on_redirect
|
||||||
|
return
|
||||||
except Exception:
|
except Exception:
|
||||||
self._hub_auth_user_cache = None
|
self._hub_auth_user_cache = None
|
||||||
raise
|
raise
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
"""mock utilities for testing"""
|
"""mock utilities for testing"""
|
||||||
|
|
||||||
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from tempfile import NamedTemporaryFile
|
from tempfile import NamedTemporaryFile
|
||||||
@@ -229,7 +230,21 @@ class MockHub(JupyterHub):
|
|||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
super().stop()
|
super().stop()
|
||||||
IOLoop().run_sync(self.cleanup)
|
|
||||||
|
# run cleanup in a background thread
|
||||||
|
# to avoid multiple eventloops in the same thread errors from asyncio
|
||||||
|
|
||||||
|
def cleanup():
|
||||||
|
loop = IOLoop.current()
|
||||||
|
loop.run_sync(self.cleanup)
|
||||||
|
loop.close()
|
||||||
|
|
||||||
|
pool = ThreadPoolExecutor(1)
|
||||||
|
f = pool.submit(cleanup)
|
||||||
|
# wait for cleanup to finish
|
||||||
|
f.result()
|
||||||
|
pool.shutdown()
|
||||||
|
|
||||||
# ignore the call that will fire in atexit
|
# ignore the call that will fire in atexit
|
||||||
self.cleanup = lambda : None
|
self.cleanup = lambda : None
|
||||||
self.db_file.close()
|
self.db_file.close()
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
alembic
|
alembic
|
||||||
traitlets>=4.3.2
|
traitlets>=4.3.2
|
||||||
tornado>=4.1,<5.0
|
tornado>=4.1
|
||||||
jinja2
|
jinja2
|
||||||
pamela
|
pamela
|
||||||
python-oauth2>=1.0
|
python-oauth2>=1.0
|
||||||
|
Reference in New Issue
Block a user