1
+ # coding: utf-8
2
+ """JupyterLab Server config"""
3
+
4
+ # Copyright (c) Jupyter Development Team.
5
+ # Distributed under the terms of the Modified BSD License.
6
+
7
+ from glob import glob
8
+ import json
9
+ from os .path import join as pjoin
10
+ import os .path as osp
11
+ import os
12
+
13
+ from jupyter_core .paths import jupyter_path
14
+ from jupyter_server .services .config .manager import ConfigManager , recursive_update
15
+ from traitlets import Bool , HasTraits , List , Unicode , default
16
+
17
+ from .server import url_path_join as ujoin
18
+
19
+
20
+ # -----------------------------------------------------------------------------
21
+ # Module globals
22
+ # -----------------------------------------------------------------------------
23
+
24
+ DEFAULT_TEMPLATE_PATH = osp .join (osp .dirname (__file__ ), 'templates' )
25
+
26
+
27
+ def get_dynamic_extensions (labextensions_path ):
28
+ """Get the metadata about dynamic extensions
29
+ """
30
+ dynamic_exts = dict ()
31
+ for ext_dir in labextensions_path :
32
+ ext_pattern = ext_dir + '/**/package.json'
33
+ for ext_path in [path for path in glob (ext_pattern , recursive = True )]:
34
+ with open (ext_path ) as fid :
35
+ data = json .load (fid )
36
+ if data ['name' ] not in dynamic_exts :
37
+ data ['ext_dir' ] = ext_dir
38
+ data ['ext_path' ] = osp .dirname (ext_path )
39
+ data ['is_local' ] = False
40
+ dynamic_exts [data ['name' ]] = data
41
+ return dynamic_exts
42
+
43
+
44
+ def get_static_page_config (app_settings_dir = None , logger = None ):
45
+ # Start with the deprecated `share/jupyter/lab/settings/page_config.json` data
46
+
47
+ cm = ConfigManager (config_dir_name = "labconfig" )
48
+ page_config = cm .get ('page_config' )
49
+
50
+ # TODO: remove in JupyterLab 4.0
51
+ if app_settings_dir :
52
+ keyname = 'disabled_labextensions'
53
+ old_page_config = pjoin (app_settings_dir , 'page_config.json' )
54
+ if osp .exists (old_page_config ):
55
+ if logger :
56
+ logger .warn ('** Upgrading deprecated page_config in %s' % old_page_config )
57
+ logger .warn ('** This will no longer have an effect in JupyterLab 4.0' )
58
+ logger .warn ('' )
59
+ with open (old_page_config ) as fid :
60
+ data = json .load (fid )
61
+ os .remove (old_page_config )
62
+ # Convert disabled_labextensions list to a dict
63
+ oldKey = "disabledExtensions"
64
+ if oldKey in data :
65
+ data [keyname ] = dict ((key , True ) for key in data [oldKey ])
66
+ del data [oldKey ]
67
+
68
+ recursive_update (page_config , data )
69
+ cm .set ('page_config' , page_config )
70
+
71
+ return page_config
72
+
73
+
74
+ def get_page_config (labextensions_path , app_settings_dir = None , logger = None ):
75
+ """Get the page config for the application"""
76
+ page_config = get_static_page_config (app_settings_dir = app_settings_dir , logger = logger )
77
+
78
+ # Handle dynamic extensions
79
+ extensions = page_config ['dynamic_extensions' ] = []
80
+ disabled_by_extensions_all = dict ()
81
+
82
+ dynamic_exts = get_dynamic_extensions (labextensions_path )
83
+
84
+ for (ext , ext_data ) in dynamic_exts .items ():
85
+ extbuild = ext_data ['jupyterlab' ]['_build' ]
86
+ extension = {
87
+ 'name' : ext_data ['name' ],
88
+ 'load' : extbuild ['load' ]
89
+ }
90
+ if 'extension' in extbuild :
91
+ extension ['extension' ] = extbuild ['extension' ]
92
+ if 'mimeExtension' in extbuild :
93
+ extension ['mimeExtension' ] = extbuild ['mimeExtension' ]
94
+ if 'style' in extbuild :
95
+ extension ['style' ] = extbuild ['style' ]
96
+ extensions .append (extension )
97
+
98
+ # If there is disabledExtensions metadata, consume it.
99
+ if ext_data ['jupyterlab' ].get ('disabledExtensions' ):
100
+ disabled_by_extensions_all [ext_data ['name' ]] = ext_data ['jupyterlab' ]['disabledExtensions' ]
101
+
102
+ disabled_by_extensions = dict ()
103
+ for name in sorted (disabled_by_extensions_all ):
104
+ disabled_list = disabled_by_extensions_all [name ]
105
+ for item in disabled_list :
106
+ disabled_by_extensions [item ] = True
107
+
108
+ disabled_extensions = disabled_by_extensions
109
+ keyname = 'disabled_labextensions'
110
+ disabled_extensions .update (page_config .get (keyname , []))
111
+ page_config [keyname ] = disabled_extensions
112
+
113
+ return page_config
114
+
115
+
116
+ def write_page_config (page_config ):
117
+ """Write page config to disk"""
118
+ cm = ConfigManager (config_dir_name = 'labconfig' )
119
+ cm .set ('page_config' , page_config )
120
+
121
+
122
+ class LabConfig (HasTraits ):
123
+ """The lab application configuration object.
124
+ """
125
+ app_name = Unicode ('' , help = 'The name of the application.' )
126
+
127
+ app_version = Unicode ('' , help = 'The version of the application.' )
128
+
129
+ app_namespace = Unicode ('' , help = 'The namespace of the application.' )
130
+
131
+ app_url = Unicode ('/lab' , help = 'The url path for the application.' )
132
+
133
+ app_settings_dir = Unicode ('' , help = 'The application settings directory.' )
134
+
135
+ extra_labextensions_path = List (Unicode (),
136
+ help = """Extra paths to look for dynamic JupyterLab extensions"""
137
+ )
138
+
139
+ labextensions_path = List (Unicode (), help = 'The standard paths to look in for dynamic JupyterLab extensions' )
140
+
141
+ templates_dir = Unicode ('' , help = 'The application templates directory.' )
142
+
143
+ static_dir = Unicode ('' ,
144
+ help = ('The optional location of local static files. '
145
+ 'If given, a static file handler will be '
146
+ 'added.' ))
147
+
148
+
149
+ labextensions_url = Unicode ('' , help = 'The url for dynamic JupyterLab extensions' )
150
+
151
+ settings_url = Unicode (help = 'The url path of the settings handler.' )
152
+
153
+ user_settings_dir = Unicode ('' ,
154
+ help = ('The optional location of the user '
155
+ 'settings directory.' ))
156
+
157
+ schemas_dir = Unicode ('' ,
158
+ help = ('The optional location of the settings '
159
+ 'schemas directory. If given, a handler will '
160
+ 'be added for settings.' ))
161
+
162
+ workspaces_api_url = Unicode (help = 'The url path of the workspaces API.' )
163
+
164
+ workspaces_dir = Unicode ('' ,
165
+ help = ('The optional location of the saved '
166
+ 'workspaces directory. If given, a handler '
167
+ 'will be added for workspaces.' ))
168
+
169
+ listings_url = Unicode (help = 'The listings url.' )
170
+
171
+ themes_url = Unicode (help = 'The theme url.' )
172
+
173
+ themes_dir = Unicode ('' ,
174
+ help = ('The optional location of the themes '
175
+ 'directory. If given, a handler will be added '
176
+ 'for themes.' ))
177
+
178
+ translations_api_url = Unicode (help = 'The url path of the translations handler.' )
179
+
180
+ tree_url = Unicode (help = 'The url path of the tree handler.' )
181
+
182
+ cache_files = Bool (True ,
183
+ help = ('Whether to cache files on the server. '
184
+ 'This should be `True` except in dev mode.' ))
185
+
186
+ @default ('template_dir' )
187
+ def _default_template_dir (self ):
188
+ return DEFAULT_TEMPLATE_PATH
189
+
190
+ @default ('labextensions_url' )
191
+ def _default_labextensions_url (self ):
192
+ return ujoin (self .app_url , "extensions/" )
193
+
194
+ @default ('labextensions_path' )
195
+ def _default_labextensions_path (self ):
196
+ return jupyter_path ('labextensions' )
197
+
198
+ @default ('workspaces_url' )
199
+ def _default_workspaces_url (self ):
200
+ return ujoin (self .app_url , 'workspaces/' )
201
+
202
+ @default ('workspaces_api_url' )
203
+ def _default_workspaces_api_url (self ):
204
+ return ujoin (self .app_url , 'api' , 'workspaces/' )
205
+
206
+ @default ('settings_url' )
207
+ def _default_settings_url (self ):
208
+ return ujoin (self .app_url , 'api' , 'settings/' )
209
+
210
+ @default ('listings_url' )
211
+ def _default_listings_url (self ):
212
+ return ujoin (self .app_url , 'api' , 'listings/' )
213
+
214
+ @default ('themes_url' )
215
+ def _default_themes_url (self ):
216
+ return ujoin (self .app_url , 'api' , 'themes/' )
217
+
218
+ @default ('tree_url' )
219
+ def _default_tree_url (self ):
220
+ return ujoin (self .app_url , 'tree/' )
221
+
222
+ @default ('translations_api_url' )
223
+ def _default_translations_api_url (self ):
224
+ return ujoin (self .app_url , 'api' , 'translations/' )
225
+
226
+ @default ('tree_url' )
227
+ def _default_tree_url (self ):
228
+ return ujoin (self .app_url , 'tree/' )
229
+
0 commit comments