Skip to content

Commit a91af4d

Browse files
committed
Update traitlets API
1 parent 0153883 commit a91af4d

File tree

6 files changed

+165
-98
lines changed

6 files changed

+165
-98
lines changed

notebook/notebookapp.py

Lines changed: 100 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878

7979
from .auth.login import LoginHandler
8080
from .auth.logout import LogoutHandler
81-
from .base.handlers import FileFindHandler, IPythonHandler
81+
from .base.handlers import FileFindHandler
8282

8383
from traitlets.config import Config
8484
from traitlets.config.application import catch_config_error, boolean_flag
@@ -91,7 +91,7 @@
9191
from nbformat.sign import NotebookNotary
9292
from traitlets import (
9393
Dict, Unicode, Integer, List, Bool, Bytes, Instance,
94-
TraitError, Type, Float
94+
TraitError, Type, Float, observe, default, validate
9595
)
9696
from ipython_genutils import py3compat
9797
from jupyter_core.paths import jupyter_runtime_dir, jupyter_path
@@ -144,7 +144,7 @@ def load_handlers(name):
144144

145145
class NotebookWebApplication(web.Application):
146146

147-
def __init__(self, ipython_app, kernel_manager, contents_manager,
147+
def __init__(self, jupyter_app, kernel_manager, contents_manager,
148148
session_manager, kernel_spec_manager,
149149
config_manager, log,
150150
base_url, default_url, settings_overrides, jinja_env_options):
@@ -157,22 +157,22 @@ def __init__(self, ipython_app, kernel_manager, contents_manager,
157157
log.info(DEV_NOTE_NPM)
158158

159159
settings = self.init_settings(
160-
ipython_app, kernel_manager, contents_manager,
160+
jupyter_app, kernel_manager, contents_manager,
161161
session_manager, kernel_spec_manager, config_manager, log, base_url,
162162
default_url, settings_overrides, jinja_env_options)
163163
handlers = self.init_handlers(settings)
164164

165165
super(NotebookWebApplication, self).__init__(handlers, **settings)
166166

167-
def init_settings(self, ipython_app, kernel_manager, contents_manager,
167+
def init_settings(self, jupyter_app, kernel_manager, contents_manager,
168168
session_manager, kernel_spec_manager,
169169
config_manager,
170170
log, base_url, default_url, settings_overrides,
171171
jinja_env_options=None):
172172

173173
_template_path = settings_overrides.get(
174174
"template_path",
175-
ipython_app.template_file_path,
175+
jupyter_app.template_file_path,
176176
)
177177
if isinstance(_template_path, py3compat.string_types):
178178
_template_path = (_template_path,)
@@ -191,7 +191,7 @@ def init_settings(self, ipython_app, kernel_manager, contents_manager,
191191
# reset the cache on server restart
192192
version_hash = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
193193

194-
if ipython_app.ignore_minified_js:
194+
if jupyter_app.ignore_minified_js:
195195
log.warn("""The `ignore_minified_js` flag is deprecated and no
196196
longer works. Alternatively use `npm run build:watch` when
197197
working on the notebook's Javascript and LESS""")
@@ -203,28 +203,28 @@ def init_settings(self, ipython_app, kernel_manager, contents_manager,
203203
base_url=base_url,
204204
default_url=default_url,
205205
template_path=template_path,
206-
static_path=ipython_app.static_file_path,
207-
static_custom_path=ipython_app.static_custom_path,
206+
static_path=jupyter_app.static_file_path,
207+
static_custom_path=jupyter_app.static_custom_path,
208208
static_handler_class = FileFindHandler,
209209
static_url_prefix = url_path_join(base_url,'/static/'),
210210
static_handler_args = {
211211
# don't cache custom.js
212212
'no_cache_paths': [url_path_join(base_url, 'static', 'custom')],
213213
},
214214
version_hash=version_hash,
215-
ignore_minified_js=ipython_app.ignore_minified_js,
215+
ignore_minified_js=jupyter_app.ignore_minified_js,
216216

217217
# rate limits
218-
iopub_msg_rate_limit=ipython_app.iopub_msg_rate_limit,
219-
iopub_data_rate_limit=ipython_app.iopub_data_rate_limit,
220-
rate_limit_window=ipython_app.rate_limit_window,
218+
iopub_msg_rate_limit=jupyter_app.iopub_msg_rate_limit,
219+
iopub_data_rate_limit=jupyter_app.iopub_data_rate_limit,
220+
rate_limit_window=jupyter_app.rate_limit_window,
221221

222222
# authentication
223-
cookie_secret=ipython_app.cookie_secret,
223+
cookie_secret=jupyter_app.cookie_secret,
224224
login_url=url_path_join(base_url,'/login'),
225-
login_handler_class=ipython_app.login_handler_class,
226-
logout_handler_class=ipython_app.logout_handler_class,
227-
password=ipython_app.password,
225+
login_handler_class=jupyter_app.login_handler_class,
226+
logout_handler_class=jupyter_app.logout_handler_class,
227+
password=jupyter_app.password,
228228

229229
# managers
230230
kernel_manager=kernel_manager,
@@ -234,13 +234,13 @@ def init_settings(self, ipython_app, kernel_manager, contents_manager,
234234
config_manager=config_manager,
235235

236236
# IPython stuff
237-
jinja_template_vars=ipython_app.jinja_template_vars,
238-
nbextensions_path=ipython_app.nbextensions_path,
239-
websocket_url=ipython_app.websocket_url,
240-
mathjax_url=ipython_app.mathjax_url,
241-
mathjax_config=ipython_app.mathjax_config,
242-
config=ipython_app.config,
243-
config_dir=ipython_app.config_dir,
237+
jinja_template_vars=jupyter_app.jinja_template_vars,
238+
nbextensions_path=jupyter_app.nbextensions_path,
239+
websocket_url=jupyter_app.websocket_url,
240+
mathjax_url=jupyter_app.mathjax_url,
241+
mathjax_config=jupyter_app.mathjax_config,
242+
config=jupyter_app.config,
243+
config_dir=jupyter_app.config_dir,
244244
jinja2_env=env,
245245
terminals_available=False, # Set later if terminals are available
246246
)
@@ -426,14 +426,17 @@ class NotebookApp(JupyterApp):
426426

427427
_log_formatter_cls = LogFormatter
428428

429-
def _log_level_default(self):
429+
@default('log_level')
430+
def _default_log_level(self):
430431
return logging.INFO
431432

432-
def _log_datefmt_default(self):
433+
@default('log_datefmt')
434+
def _default_log_datefmt(self):
433435
"""Exclude date from default date format"""
434436
return "%H:%M:%S"
435437

436-
def _log_format_default(self):
438+
@default('log_format')
439+
def _default_log_format(self):
437440
"""override default log format to include time"""
438441
return u"%(color)s[%(levelname)1.1s %(asctime)s.%(msecs).03d %(name)s]%(end_color)s %(message)s"
439442

@@ -484,7 +487,9 @@ def _log_format_default(self):
484487
ip = Unicode('localhost', config=True,
485488
help="The IP address the notebook server will listen on."
486489
)
487-
def _ip_default(self):
490+
491+
@default('ip')
492+
def _default_ip(self):
488493
"""Return localhost if available, 127.0.0.1 otherwise.
489494
490495
On some (horribly broken) systems, localhost cannot be bound.
@@ -499,12 +504,17 @@ def _ip_default(self):
499504
s.close()
500505
return 'localhost'
501506

502-
def _ip_changed(self, name, old, new):
503-
if new == u'*': self.ip = u''
507+
@validate('ip')
508+
def _valdate_ip(self, proposal):
509+
value = proposal['value']
510+
if value == u'*':
511+
value = u''
512+
return value
504513

505514
port = Integer(8888, config=True,
506515
help="The port the notebook server will listen on."
507516
)
517+
508518
port_retries = Integer(50, config=True,
509519
help="The number of additional ports to try if the specified port is not available."
510520
)
@@ -524,7 +534,9 @@ def _ip_changed(self, name, old, new):
524534
cookie_secret_file = Unicode(config=True,
525535
help="""The file where the cookie secret is stored."""
526536
)
527-
def _cookie_secret_file_default(self):
537+
538+
@default('cookie_secret_file')
539+
def _default_cookie_secret_file(self):
528540
return os.path.join(self.runtime_dir, 'notebook_cookie_secret')
529541

530542
cookie_secret = Bytes(b'', config=True,
@@ -536,7 +548,9 @@ def _cookie_secret_file_default(self):
536548
cookie_secret stored in plaintext (you can read the value from a file).
537549
"""
538550
)
539-
def _cookie_secret_default(self):
551+
552+
@default('cookie_secret')
553+
def _default_cookie_secret(self):
540554
if os.path.exists(self.cookie_secret_file):
541555
with io.open(self.cookie_secret_file, 'rb') as f:
542556
return f.read()
@@ -599,9 +613,11 @@ def _write_cookie_secret_file(self, secret):
599613
webapp_settings = Dict(config=True,
600614
help="DEPRECATED, use tornado_settings"
601615
)
602-
def _webapp_settings_changed(self, name, old, new):
616+
617+
@observe('webapp_settings')
618+
def _update_webapp_settings(self, change):
603619
self.log.warning("\n webapp_settings is deprecated, use tornado_settings.\n")
604-
self.tornado_settings = new
620+
self.tornado_settings = change['new']
605621

606622
tornado_settings = Dict(config=True,
607623
help="Supply overrides for the tornado.web.Application that the "
@@ -636,9 +652,11 @@ def _webapp_settings_changed(self, name, old, new):
636652
When disabled, equations etc. will appear as their untransformed TeX source.
637653
"""
638654
)
639-
def _enable_mathjax_changed(self, name, old, new):
655+
656+
@observe('enable_mathjax')
657+
def _update_enable_mathjax(self, change):
640658
"""set mathjax url to empty if mathjax is disabled"""
641-
if not new:
659+
if not change['new']:
642660
self.mathjax_url = u''
643661

644662
base_url = Unicode('/', config=True,
@@ -647,16 +665,22 @@ def _enable_mathjax_changed(self, name, old, new):
647665
Leading and trailing slashes can be omitted,
648666
and will automatically be added.
649667
''')
650-
def _base_url_changed(self, name, old, new):
651-
if not new.startswith('/'):
652-
self.base_url = '/'+new
653-
elif not new.endswith('/'):
654-
self.base_url = new+'/'
668+
669+
@validate('base_url')
670+
def _update_base_url(self, proposal):
671+
value = proposal['value']
672+
if not value.startswith('/'):
673+
value = '/' + value
674+
elif not value.endswith('/'):
675+
value = value + '/'
676+
return value
655677

656678
base_project_url = Unicode('/', config=True, help="""DEPRECATED use base_url""")
657-
def _base_project_url_changed(self, name, old, new):
679+
680+
@observe('base_project_url')
681+
def _update_base_project_url(self, change):
658682
self.log.warning("base_project_url is deprecated, use base_url")
659-
self.base_url = new
683+
self.base_url = change['new']
660684

661685
extra_static_paths = List(Unicode(), config=True,
662686
help="""Extra paths to search for serving static files.
@@ -673,7 +697,9 @@ def static_file_path(self):
673697
static_custom_path = List(Unicode(),
674698
help="""Path to search for custom.js, css"""
675699
)
676-
def _static_custom_path_default(self):
700+
701+
@default('static_custom_path')
702+
def _default_static_custom_path(self):
677703
return [
678704
os.path.join(d, 'custom') for d in (
679705
self.config_dir,
@@ -715,16 +741,21 @@ def nbextensions_path(self):
715741
Should be in the form of an HTTP origin: ws[s]://hostname[:port]
716742
"""
717743
)
744+
718745
mathjax_url = Unicode("", config=True,
719746
help="""The url for MathJax.js."""
720747
)
721-
def _mathjax_url_default(self):
748+
749+
@default('mathjax_url')
750+
def _default_mathjax_url(self):
722751
if not self.enable_mathjax:
723752
return u''
724753
static_url_prefix = self.tornado_settings.get("static_url_prefix", "static")
725754
return url_path_join(static_url_prefix, 'components', 'MathJax', 'MathJax.js')
726755

727-
def _mathjax_url_changed(self, name, old, new):
756+
@observe('mathjax_url')
757+
def _update_mathjax_url(self, change):
758+
new = change['new']
728759
if new and not self.enable_mathjax:
729760
# enable_mathjax=False overrides mathjax_url
730761
self.mathjax_url = u''
@@ -735,20 +766,23 @@ def _mathjax_url_changed(self, name, old, new):
735766
help="""The MathJax.js configuration file that is to be used."""
736767
)
737768

738-
def _mathjax_config_changed(self, name, old, new):
739-
self.log.info("Using MathJax configuration file: %s", new)
769+
@observe('mathjax_config')
770+
def _update_mathjax_config(self, change):
771+
self.log.info("Using MathJax configuration file: %s", change['new'])
740772

741773
contents_manager_class = Type(
742774
default_value=FileContentsManager,
743775
klass=ContentsManager,
744776
config=True,
745777
help='The notebook manager class to use.'
746778
)
779+
747780
kernel_manager_class = Type(
748781
default_value=MappingKernelManager,
749782
config=True,
750783
help='The kernel manager class to use.'
751784
)
785+
752786
session_manager_class = Type(
753787
default_value=SessionManager,
754788
config=True,
@@ -796,7 +830,8 @@ def _mathjax_config_changed(self, name, old, new):
796830

797831
info_file = Unicode()
798832

799-
def _info_file_default(self):
833+
@default('info_file')
834+
def _default_info_file(self):
800835
info_file = "nbserver-%s.json" % os.getpid()
801836
return os.path.join(self.runtime_dir, info_file)
802837

@@ -805,10 +840,12 @@ def _info_file_default(self):
805840
DISABLED: use %pylab or %matplotlib in the notebook to enable matplotlib.
806841
"""
807842
)
808-
def _pylab_changed(self, name, old, new):
843+
844+
@observe('pylab')
845+
def _update_pylab(self, change):
809846
"""when --pylab is specified, display a warning and exit"""
810847
if new != 'warn':
811-
backend = ' %s' % new
848+
backend = ' %s' % change['new']
812849
else:
813850
backend = ''
814851
self.log.error("Support for specifying --pylab on the command line has been removed.")
@@ -821,41 +858,46 @@ def _pylab_changed(self, name, old, new):
821858
help="The directory to use for notebooks and kernels."
822859
)
823860

824-
def _notebook_dir_default(self):
861+
@default('notebook_dir')
862+
def _default_notebook_dir(self):
825863
if self.file_to_run:
826864
return os.path.dirname(os.path.abspath(self.file_to_run))
827865
else:
828866
return py3compat.getcwd()
829867

830-
def _notebook_dir_validate(self, value, trait):
868+
@validate('notebook_dir')
869+
def _notebook_dir_validate(self, proposal):
870+
value = proposal['value']
831871
# Strip any trailing slashes
832872
# *except* if it's root
833873
_, path = os.path.splitdrive(value)
834874
if path == os.sep:
835875
return value
836-
837876
value = value.rstrip(os.sep)
838-
839877
if not os.path.isabs(value):
840878
# If we receive a non-absolute path, make it absolute.
841879
value = os.path.abspath(value)
842880
if not os.path.isdir(value):
843881
raise TraitError("No such notebook dir: %r" % value)
844882
return value
845883

846-
def _notebook_dir_changed(self, name, old, new):
884+
@observe('notebook_dir')
885+
def _update_notebook_dir(self, change):
847886
"""Do a bit of validation of the notebook dir."""
848887
# setting App.notebook_dir implies setting notebook and kernel dirs as well
888+
new = change['new']
849889
self.config.FileContentsManager.root_dir = new
850890
self.config.MappingKernelManager.root_dir = new
851891

852892
# TODO: Remove me in notebook 5.0
853893
server_extensions = List(Unicode(), config=True,
854894
help=("DEPRECATED use the nbserver_extensions dict instead")
855895
)
856-
def _server_extensions_changed(self, name, old, new):
896+
897+
@observe('server_extensions')
898+
def _update_server_extensions(self, change):
857899
self.log.warning("server_extensions is deprecated, use nbserver_extensions")
858-
self.server_extensions = new
900+
self.server_extensions = change['new']
859901

860902
nbserver_extensions = Dict({}, config=True,
861903
help=("Dict of Python modules to load as notebook server extensions."

0 commit comments

Comments
 (0)