78
78
79
79
from .auth .login import LoginHandler
80
80
from .auth .logout import LogoutHandler
81
- from .base .handlers import FileFindHandler , IPythonHandler
81
+ from .base .handlers import FileFindHandler
82
82
83
83
from traitlets .config import Config
84
84
from traitlets .config .application import catch_config_error , boolean_flag
91
91
from nbformat .sign import NotebookNotary
92
92
from traitlets import (
93
93
Dict , Unicode , Integer , List , Bool , Bytes , Instance ,
94
- TraitError , Type , Float
94
+ TraitError , Type , Float , observe , default , validate
95
95
)
96
96
from ipython_genutils import py3compat
97
97
from jupyter_core .paths import jupyter_runtime_dir , jupyter_path
@@ -144,7 +144,7 @@ def load_handlers(name):
144
144
145
145
class NotebookWebApplication (web .Application ):
146
146
147
- def __init__ (self , ipython_app , kernel_manager , contents_manager ,
147
+ def __init__ (self , jupyter_app , kernel_manager , contents_manager ,
148
148
session_manager , kernel_spec_manager ,
149
149
config_manager , log ,
150
150
base_url , default_url , settings_overrides , jinja_env_options ):
@@ -157,22 +157,22 @@ def __init__(self, ipython_app, kernel_manager, contents_manager,
157
157
log .info (DEV_NOTE_NPM )
158
158
159
159
settings = self .init_settings (
160
- ipython_app , kernel_manager , contents_manager ,
160
+ jupyter_app , kernel_manager , contents_manager ,
161
161
session_manager , kernel_spec_manager , config_manager , log , base_url ,
162
162
default_url , settings_overrides , jinja_env_options )
163
163
handlers = self .init_handlers (settings )
164
164
165
165
super (NotebookWebApplication , self ).__init__ (handlers , ** settings )
166
166
167
- def init_settings (self , ipython_app , kernel_manager , contents_manager ,
167
+ def init_settings (self , jupyter_app , kernel_manager , contents_manager ,
168
168
session_manager , kernel_spec_manager ,
169
169
config_manager ,
170
170
log , base_url , default_url , settings_overrides ,
171
171
jinja_env_options = None ):
172
172
173
173
_template_path = settings_overrides .get (
174
174
"template_path" ,
175
- ipython_app .template_file_path ,
175
+ jupyter_app .template_file_path ,
176
176
)
177
177
if isinstance (_template_path , py3compat .string_types ):
178
178
_template_path = (_template_path ,)
@@ -191,7 +191,7 @@ def init_settings(self, ipython_app, kernel_manager, contents_manager,
191
191
# reset the cache on server restart
192
192
version_hash = datetime .datetime .now ().strftime ("%Y%m%d%H%M%S" )
193
193
194
- if ipython_app .ignore_minified_js :
194
+ if jupyter_app .ignore_minified_js :
195
195
log .warn ("""The `ignore_minified_js` flag is deprecated and no
196
196
longer works. Alternatively use `npm run build:watch` when
197
197
working on the notebook's Javascript and LESS""" )
@@ -203,28 +203,28 @@ def init_settings(self, ipython_app, kernel_manager, contents_manager,
203
203
base_url = base_url ,
204
204
default_url = default_url ,
205
205
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 ,
208
208
static_handler_class = FileFindHandler ,
209
209
static_url_prefix = url_path_join (base_url ,'/static/' ),
210
210
static_handler_args = {
211
211
# don't cache custom.js
212
212
'no_cache_paths' : [url_path_join (base_url , 'static' , 'custom' )],
213
213
},
214
214
version_hash = version_hash ,
215
- ignore_minified_js = ipython_app .ignore_minified_js ,
215
+ ignore_minified_js = jupyter_app .ignore_minified_js ,
216
216
217
217
# 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 ,
221
221
222
222
# authentication
223
- cookie_secret = ipython_app .cookie_secret ,
223
+ cookie_secret = jupyter_app .cookie_secret ,
224
224
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 ,
228
228
229
229
# managers
230
230
kernel_manager = kernel_manager ,
@@ -234,13 +234,13 @@ def init_settings(self, ipython_app, kernel_manager, contents_manager,
234
234
config_manager = config_manager ,
235
235
236
236
# 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 ,
244
244
jinja2_env = env ,
245
245
terminals_available = False , # Set later if terminals are available
246
246
)
@@ -426,14 +426,17 @@ class NotebookApp(JupyterApp):
426
426
427
427
_log_formatter_cls = LogFormatter
428
428
429
- def _log_level_default (self ):
429
+ @default ('log_level' )
430
+ def _default_log_level (self ):
430
431
return logging .INFO
431
432
432
- def _log_datefmt_default (self ):
433
+ @default ('log_datefmt' )
434
+ def _default_log_datefmt (self ):
433
435
"""Exclude date from default date format"""
434
436
return "%H:%M:%S"
435
437
436
- def _log_format_default (self ):
438
+ @default ('log_format' )
439
+ def _default_log_format (self ):
437
440
"""override default log format to include time"""
438
441
return u"%(color)s[%(levelname)1.1s %(asctime)s.%(msecs).03d %(name)s]%(end_color)s %(message)s"
439
442
@@ -484,7 +487,9 @@ def _log_format_default(self):
484
487
ip = Unicode ('localhost' , config = True ,
485
488
help = "The IP address the notebook server will listen on."
486
489
)
487
- def _ip_default (self ):
490
+
491
+ @default ('ip' )
492
+ def _default_ip (self ):
488
493
"""Return localhost if available, 127.0.0.1 otherwise.
489
494
490
495
On some (horribly broken) systems, localhost cannot be bound.
@@ -499,12 +504,17 @@ def _ip_default(self):
499
504
s .close ()
500
505
return 'localhost'
501
506
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
504
513
505
514
port = Integer (8888 , config = True ,
506
515
help = "The port the notebook server will listen on."
507
516
)
517
+
508
518
port_retries = Integer (50 , config = True ,
509
519
help = "The number of additional ports to try if the specified port is not available."
510
520
)
@@ -524,7 +534,9 @@ def _ip_changed(self, name, old, new):
524
534
cookie_secret_file = Unicode (config = True ,
525
535
help = """The file where the cookie secret is stored."""
526
536
)
527
- def _cookie_secret_file_default (self ):
537
+
538
+ @default ('cookie_secret_file' )
539
+ def _default_cookie_secret_file (self ):
528
540
return os .path .join (self .runtime_dir , 'notebook_cookie_secret' )
529
541
530
542
cookie_secret = Bytes (b'' , config = True ,
@@ -536,7 +548,9 @@ def _cookie_secret_file_default(self):
536
548
cookie_secret stored in plaintext (you can read the value from a file).
537
549
"""
538
550
)
539
- def _cookie_secret_default (self ):
551
+
552
+ @default ('cookie_secret' )
553
+ def _default_cookie_secret (self ):
540
554
if os .path .exists (self .cookie_secret_file ):
541
555
with io .open (self .cookie_secret_file , 'rb' ) as f :
542
556
return f .read ()
@@ -599,9 +613,11 @@ def _write_cookie_secret_file(self, secret):
599
613
webapp_settings = Dict (config = True ,
600
614
help = "DEPRECATED, use tornado_settings"
601
615
)
602
- def _webapp_settings_changed (self , name , old , new ):
616
+
617
+ @observe ('webapp_settings' )
618
+ def _update_webapp_settings (self , change ):
603
619
self .log .warning ("\n webapp_settings is deprecated, use tornado_settings.\n " )
604
- self .tornado_settings = new
620
+ self .tornado_settings = change [ ' new' ]
605
621
606
622
tornado_settings = Dict (config = True ,
607
623
help = "Supply overrides for the tornado.web.Application that the "
@@ -636,9 +652,11 @@ def _webapp_settings_changed(self, name, old, new):
636
652
When disabled, equations etc. will appear as their untransformed TeX source.
637
653
"""
638
654
)
639
- def _enable_mathjax_changed (self , name , old , new ):
655
+
656
+ @observe ('enable_mathjax' )
657
+ def _update_enable_mathjax (self , change ):
640
658
"""set mathjax url to empty if mathjax is disabled"""
641
- if not new :
659
+ if not change [ ' new' ] :
642
660
self .mathjax_url = u''
643
661
644
662
base_url = Unicode ('/' , config = True ,
@@ -647,16 +665,22 @@ def _enable_mathjax_changed(self, name, old, new):
647
665
Leading and trailing slashes can be omitted,
648
666
and will automatically be added.
649
667
''' )
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
655
677
656
678
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 ):
658
682
self .log .warning ("base_project_url is deprecated, use base_url" )
659
- self .base_url = new
683
+ self .base_url = change [ ' new' ]
660
684
661
685
extra_static_paths = List (Unicode (), config = True ,
662
686
help = """Extra paths to search for serving static files.
@@ -673,7 +697,9 @@ def static_file_path(self):
673
697
static_custom_path = List (Unicode (),
674
698
help = """Path to search for custom.js, css"""
675
699
)
676
- def _static_custom_path_default (self ):
700
+
701
+ @default ('static_custom_path' )
702
+ def _default_static_custom_path (self ):
677
703
return [
678
704
os .path .join (d , 'custom' ) for d in (
679
705
self .config_dir ,
@@ -715,16 +741,21 @@ def nbextensions_path(self):
715
741
Should be in the form of an HTTP origin: ws[s]://hostname[:port]
716
742
"""
717
743
)
744
+
718
745
mathjax_url = Unicode ("" , config = True ,
719
746
help = """The url for MathJax.js."""
720
747
)
721
- def _mathjax_url_default (self ):
748
+
749
+ @default ('mathjax_url' )
750
+ def _default_mathjax_url (self ):
722
751
if not self .enable_mathjax :
723
752
return u''
724
753
static_url_prefix = self .tornado_settings .get ("static_url_prefix" , "static" )
725
754
return url_path_join (static_url_prefix , 'components' , 'MathJax' , 'MathJax.js' )
726
755
727
- def _mathjax_url_changed (self , name , old , new ):
756
+ @observe ('mathjax_url' )
757
+ def _update_mathjax_url (self , change ):
758
+ new = change ['new' ]
728
759
if new and not self .enable_mathjax :
729
760
# enable_mathjax=False overrides mathjax_url
730
761
self .mathjax_url = u''
@@ -735,20 +766,23 @@ def _mathjax_url_changed(self, name, old, new):
735
766
help = """The MathJax.js configuration file that is to be used."""
736
767
)
737
768
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' ])
740
772
741
773
contents_manager_class = Type (
742
774
default_value = FileContentsManager ,
743
775
klass = ContentsManager ,
744
776
config = True ,
745
777
help = 'The notebook manager class to use.'
746
778
)
779
+
747
780
kernel_manager_class = Type (
748
781
default_value = MappingKernelManager ,
749
782
config = True ,
750
783
help = 'The kernel manager class to use.'
751
784
)
785
+
752
786
session_manager_class = Type (
753
787
default_value = SessionManager ,
754
788
config = True ,
@@ -796,7 +830,8 @@ def _mathjax_config_changed(self, name, old, new):
796
830
797
831
info_file = Unicode ()
798
832
799
- def _info_file_default (self ):
833
+ @default ('info_file' )
834
+ def _default_info_file (self ):
800
835
info_file = "nbserver-%s.json" % os .getpid ()
801
836
return os .path .join (self .runtime_dir , info_file )
802
837
@@ -805,10 +840,12 @@ def _info_file_default(self):
805
840
DISABLED: use %pylab or %matplotlib in the notebook to enable matplotlib.
806
841
"""
807
842
)
808
- def _pylab_changed (self , name , old , new ):
843
+
844
+ @observe ('pylab' )
845
+ def _update_pylab (self , change ):
809
846
"""when --pylab is specified, display a warning and exit"""
810
847
if new != 'warn' :
811
- backend = ' %s' % new
848
+ backend = ' %s' % change [ ' new' ]
812
849
else :
813
850
backend = ''
814
851
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):
821
858
help = "The directory to use for notebooks and kernels."
822
859
)
823
860
824
- def _notebook_dir_default (self ):
861
+ @default ('notebook_dir' )
862
+ def _default_notebook_dir (self ):
825
863
if self .file_to_run :
826
864
return os .path .dirname (os .path .abspath (self .file_to_run ))
827
865
else :
828
866
return py3compat .getcwd ()
829
867
830
- def _notebook_dir_validate (self , value , trait ):
868
+ @validate ('notebook_dir' )
869
+ def _notebook_dir_validate (self , proposal ):
870
+ value = proposal ['value' ]
831
871
# Strip any trailing slashes
832
872
# *except* if it's root
833
873
_ , path = os .path .splitdrive (value )
834
874
if path == os .sep :
835
875
return value
836
-
837
876
value = value .rstrip (os .sep )
838
-
839
877
if not os .path .isabs (value ):
840
878
# If we receive a non-absolute path, make it absolute.
841
879
value = os .path .abspath (value )
842
880
if not os .path .isdir (value ):
843
881
raise TraitError ("No such notebook dir: %r" % value )
844
882
return value
845
883
846
- def _notebook_dir_changed (self , name , old , new ):
884
+ @observe ('notebook_dir' )
885
+ def _update_notebook_dir (self , change ):
847
886
"""Do a bit of validation of the notebook dir."""
848
887
# setting App.notebook_dir implies setting notebook and kernel dirs as well
888
+ new = change ['new' ]
849
889
self .config .FileContentsManager .root_dir = new
850
890
self .config .MappingKernelManager .root_dir = new
851
891
852
892
# TODO: Remove me in notebook 5.0
853
893
server_extensions = List (Unicode (), config = True ,
854
894
help = ("DEPRECATED use the nbserver_extensions dict instead" )
855
895
)
856
- def _server_extensions_changed (self , name , old , new ):
896
+
897
+ @observe ('server_extensions' )
898
+ def _update_server_extensions (self , change ):
857
899
self .log .warning ("server_extensions is deprecated, use nbserver_extensions" )
858
- self .server_extensions = new
900
+ self .server_extensions = change [ ' new' ]
859
901
860
902
nbserver_extensions = Dict ({}, config = True ,
861
903
help = ("Dict of Python modules to load as notebook server extensions."
0 commit comments