use traitlets-4.1 observe/default decorators

This commit is contained in:
Min RK
2016-03-27 10:41:36 -07:00
parent fa48620076
commit 7a2794af7c
6 changed files with 56 additions and 19 deletions

View File

@@ -36,6 +36,7 @@ from tornado import gen, web
from traitlets import (
Unicode, Integer, Dict, TraitError, List, Bool, Any,
Type, Set, Instance, Bytes, Float,
observe, default,
)
from traitlets.config import Application, catch_config_error
@@ -209,6 +210,7 @@ class JupyterHub(Application):
help="Paths to search for jinja templates.",
).tag(config=True)
@default('template_paths')
def _template_paths_default(self):
return [os.path.join(self.data_files_path, 'templates')]
@@ -262,6 +264,8 @@ class JupyterHub(Application):
logo_file = Unicode('',
help="Specify path to a logo image to override the Jupyter logo in the banner."
).tag(config=True)
@default('logo_file')
def _logo_file_default(self):
return os.path.join(self.data_files_path, 'static', 'images', 'jupyter.png')
@@ -284,6 +288,8 @@ class JupyterHub(Application):
Loaded from the CONFIGPROXY_AUTH_TOKEN env variable by default.
"""
).tag(config=True)
@default('proxy_auth_token')
def _proxy_auth_token_default(self):
token = os.environ.get('CONFIGPROXY_AUTH_TOKEN', None)
if not token:
@@ -302,6 +308,8 @@ class JupyterHub(Application):
proxy_api_port = Integer(
help="The port for the proxy API handlers"
).tag(config=True)
@default('proxy_api_port')
def _proxy_api_port_default(self):
return self.port + 1
@@ -314,21 +322,27 @@ class JupyterHub(Application):
hub_prefix = URLPrefix('/hub/',
help="The prefix for the hub server. Must not be '/'"
).tag(config=True)
@default('hub_prefix')
def _hub_prefix_default(self):
return url_path_join(self.base_url, '/hub/')
@observe('hub_prefix')
def _hub_prefix_changed(self, name, old, new):
if new == '/':
raise TraitError("'/' is not a valid hub prefix")
if not new.startswith(self.base_url):
self.hub_prefix = url_path_join(self.base_url, new)
cookie_secret = Bytes(env='JPY_COOKIE_SECRET',
cookie_secret = Bytes(
help="""The cookie secret to use to encrypt cookies.
Loaded from the JPY_COOKIE_SECRET env variable by default.
"""
).tag(config=True)
).tag(
config=True,
env='JPY_COOKIE_SECRET',
)
cookie_secret_file = Unicode('jupyterhub_cookie_secret',
help="""File in which to store the cookie secret."""
@@ -350,6 +364,8 @@ class JupyterHub(Application):
).tag(config=True)
authenticator = Instance(Authenticator)
@default('authenticator')
def _authenticator_default(self):
return self.authenticator_class(parent=self, db=self.db)
@@ -364,7 +380,10 @@ class JupyterHub(Application):
db_url = Unicode('sqlite:///jupyterhub.sqlite',
help="url for the database. e.g. `sqlite:///jupyterhub.sqlite`"
).tag(config=True)
def _db_url_changed(self, name, old, new):
@observe('db_url')
def _db_url_changed(self, change):
new = change['new']
if '://' not in new:
# assume sqlite, if given as a plain filename
self.db_url = 'sqlite:///%s' % new
@@ -384,6 +403,8 @@ class JupyterHub(Application):
session_factory = Any()
users = Instance(UserDict)
@default('users')
def _users_default(self):
assert self.tornado_settings
return UserDict(db_factory=lambda : self.db, settings=self.tornado_settings)
@@ -435,13 +456,16 @@ class JupyterHub(Application):
proxy_process = None
io_loop = None
@default('log_level')
def _log_level_default(self):
return logging.INFO
@default('log_datefmt')
def _log_datefmt_default(self):
"""Exclude date from default date format"""
return "%Y-%m-%d %H:%M:%S"
@default('log_format')
def _log_format_default(self):
"""override default log format to include time"""
return "%(color)s[%(levelname)1.1s %(asctime)s.%(msecs).03d %(name)s %(module)s:%(lineno)d]%(end_color)s %(message)s"
@@ -537,7 +561,7 @@ class JupyterHub(Application):
def init_secrets(self):
trait_name = 'cookie_secret'
trait = self.traits()[trait_name]
env_name = trait.get_metadata('env')
env_name = trait.metadata.get('env')
secret_file = os.path.abspath(
os.path.expanduser(self.cookie_secret_file)
)

View File

@@ -15,7 +15,7 @@ from tornado import gen
import pamela
from traitlets.config import LoggingConfigurable
from traitlets import Bool, Set, Unicode, Dict, Any
from traitlets import Bool, Set, Unicode, Dict, Any, default, observe
from .handlers.login import LoginHandler
from .utils import url_path_join
@@ -61,10 +61,11 @@ class Authenticator(LoggingConfigurable):
If not defined: allow any username.
"""
).tag(config=True)
def _username_pattern_changed(self, name, old, new):
if not new:
@observe('username_pattern')
def _username_pattern_changed(self, change):
if not change['new']:
self.username_regex = None
self.username_regex = re.compile(new)
self.username_regex = re.compile(change['new'])
username_regex = Any()
@@ -272,6 +273,8 @@ class LocalAuthenticator(Authenticator):
when the user 'river' is created.
"""
).tag(config=True)
@default('add_user_cmd')
def _add_user_cmd_default(self):
if sys.platform == 'darwin':
raise ValueError("I don't know how to create users on OS X")
@@ -285,10 +288,10 @@ class LocalAuthenticator(Authenticator):
group_whitelist = Set(
help="Automatically whitelist anyone in this group.",
).tag(config=True)
def _group_whitelist_changed(self, name, old, new):
@observe('group_whitelist')
def _group_whitelist_changed(self, change):
if self.whitelist:
self.log.warn(
self.log.warning(
"Ignoring username whitelist because group whitelist supplied!"
)

View File

@@ -128,7 +128,7 @@ class Spawner(LoggingConfigurable):
cmd = Command(['jupyterhub-singleuser'],
help="""The command used for starting notebooks."""
).tag(config=True)
args = List(Unicode,
args = List(Unicode(),
help="""Extra arguments to be passed to the single-user server"""
).tag(config=True)

View File

@@ -13,6 +13,8 @@ from tornado import gen
from tornado.concurrent import Future
from tornado.ioloop import IOLoop
from traitlets import default
from ..app import JupyterHub
from ..auth import PAMAuthenticator
from .. import orm
@@ -44,7 +46,7 @@ class MockSpawner(LocalProcessSpawner):
def user_env(self, env):
return env
@default('cmd')
def _cmd_default(self):
return [sys.executable, '-m', 'jupyterhub.tests.mocksu']
@@ -66,6 +68,7 @@ class SlowSpawner(MockSpawner):
class NeverSpawner(MockSpawner):
"""A spawner that will never start"""
@default('start_timeout')
def _start_timeout_default(self):
return 1
@@ -90,6 +93,7 @@ class FormSpawner(MockSpawner):
class MockPAMAuthenticator(PAMAuthenticator):
@default('admin_users')
def _admin_users_default(self):
return {'admin'}
@@ -113,15 +117,19 @@ class MockHub(JupyterHub):
last_activity_interval = 2
@default('subdomain_host')
def _subdomain_host_default(self):
return os.environ.get('JUPYTERHUB_TEST_SUBDOMAIN_HOST', '')
@default('ip')
def _ip_default(self):
return '127.0.0.1'
@default('authenticator_class')
def _authenticator_class_default(self):
return MockPAMAuthenticator
@default('spawner_class')
def _spawner_class_default(self):
return MockSpawner

View File

@@ -21,7 +21,7 @@ class Command(List):
kwargs.setdefault('minlen', 1)
if isinstance(default_value, str):
default_value = [default_value]
super().__init__(Unicode, default_value, **kwargs)
super().__init__(Unicode(), default_value, **kwargs)
def validate(self, obj, value):
if isinstance(value, str):

View File

@@ -12,7 +12,7 @@ from sqlalchemy import inspect
from .utils import url_path_join
from . import orm
from traitlets import HasTraits, Any, Dict
from traitlets import HasTraits, Any, Dict, observe, default
from .spawner import LocalProcessSpawner
@@ -41,7 +41,7 @@ class UserDict(dict):
elif isinstance(key, str):
orm_user = self.db.query(orm.User).filter(orm.User.name==key).first()
if orm_user is None:
raise KeyError("No such user: %s" % name)
raise KeyError("No such user: %s" % key)
else:
key = orm_user
if isinstance(key, orm.User):
@@ -75,22 +75,24 @@ class UserDict(dict):
class User(HasTraits):
@default('log')
def _log_default(self):
return app_log
settings = Dict()
db = Any(allow_none=True)
@default('db')
def _db_default(self):
if self.orm_user:
return inspect(self.orm_user).session
def _db_changed(self, name, old, new):
@observe('db')
def _db_changed(self, change):
"""Changing db session reacquires ORM User object"""
# db session changed, re-get orm User
if self.orm_user:
id = self.orm_user.id
self.orm_user = new.query(orm.User).filter(orm.User.id==id).first()
self.orm_user = change['new'].query(orm.User).filter(orm.User.id==id).first()
self.spawner.db = self.db
orm_user = None