Skip to content

Commit 5d9b409

Browse files
afshinblink1073
authored andcommitted
Workspaces CLI (jupyterlab#5166)
* Formatting/documentation clean up. * Create shell classes for workspaces CLI. * Grab which workspace to export from CLI args. * Switch jupyterlab_launcher to jupyterlab_server, PEP 8 compliance * More PEP 8 appeasement. * Initial implementation of export functionality. * Clean up. * Initial implementation of workspace import. * Create the workspaes directory upon import if it does not already exist. * Remove duplicate package.json in manifest. * Wait longer for Chrome headless test on CI. * Update browser test logic. * Fix integrity test. * Fix docs test. * Fix cli script * revert docs change * try reordering * revert change to script * Try original file * Fix printing of app directory in dev-mode * Override config app dir * Clean up handling of app_dir * Print the page content on error * cleanup chrome-test * cleanup chrome-test * more debug * more debug * more debug * Fix handling of timeout * cleanup * Update staging index * add handling of core dir
1 parent f24436d commit 5d9b409

File tree

23 files changed

+380
-167
lines changed

23 files changed

+380
-167
lines changed

MANIFEST.in

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ include package.json
22
include LICENSE
33
include CONTRIBUTING.md
44
include README.md
5-
include package.json
65
include setupbase.py
76

87
# Documentation

clean.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
for (root, dnames, files) in os.walk(here):
1010
if 'node_modules' in dnames:
1111
subprocess.check_call(['rmdir', '/s', '/q', 'node_modules'],
12-
cwd=root, shell=True)
12+
cwd=root, shell=True)
1313
dnames.remove('node_modules')
1414

1515

dev_mode/index.js

+28-9
Original file line numberDiff line numberDiff line change
@@ -162,20 +162,39 @@ function main() {
162162

163163
// Handle a browser test.
164164
var browserTest = PageConfig.getOption('browserTest');
165+
var el = document.createElement('div');
166+
el.id = 'browserTest';
167+
document.body.appendChild(el);
168+
el.textContent = '[]';
169+
165170
if (browserTest.toLowerCase() === 'true') {
166-
var caught_errors = [];
171+
var errors = [];
172+
var reported = false;
173+
var timeout = 25000;
174+
175+
var report = function(errors) {
176+
if (reported) {
177+
return;
178+
}
179+
reported = true;
180+
el.className = 'completed';
181+
}
182+
167183
window.onerror = function(msg, url, line, col, error) {
168-
caught_errors.push(String(error));
184+
errors.push(String(error));
185+
el.textContent = JSON.stringify(errors)
169186
};
170187
console.error = function(message) {
171-
caught_errors.push(String(message));
188+
errors.push(String(message));
189+
el.textContent = JSON.stringify(errors)
172190
};
173-
lab.restored.then(function() {
174-
var el = document.createElement('div');
175-
el.id = 'browserResult';
176-
el.textContent = JSON.stringify(caught_errors);
177-
document.body.appendChild(el);
178-
});
191+
192+
lab.restored
193+
.then(function() { report(errors); })
194+
.catch(function(reason) { report([`RestoreError: ${reason.message}`]); });
195+
196+
// Handle failures to restore after the timeout has elapsed.
197+
window.setTimeout(function() { report(errors); }, timeout);
179198
}
180199

181200
}

docs/source/getting_started/changelog.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ Changes for developers
367367
widget for a markdown file is a text editor, but the default rendered
368368
widget is the markdown viewer.
369369
(`#4692 <https://github.com/jupyterlab/jupyterlab/pull/4692>`__)
370-
- Add new workspace REST endpoints to ``jupyterlab_launcher`` and make
370+
- Add new workspace REST endpoints to ``jupyterlab_server`` and make
371371
them available in ``@jupyterlab/services``.
372372
(`#4841 <https://github.com/jupyterlab/jupyterlab/pull/4841>`__)
373373
- Documents created with a mimerenderer extension can now be accessed
@@ -481,7 +481,7 @@ Changes in the JupyterLab code infrastructure include:
481481
We will upgrade yarn, with NodeJS version 10 support, when a `bug in
482482
yarn <https://github.com/yarnpkg/yarn/issues/5935>`__ is fixed.
483483
(`#4804 <https://github.com/jupyterlab/jupyterlab/pull/4804>`__)
484-
- Various process utilities were moved to ``jupyterlab_launcher``.
484+
- Various process utilities were moved to ``jupyterlab_server``.
485485
(`#4696 <https://github.com/jupyterlab/jupyterlab/pull/4696>`__)
486486

487487
Other fixes

examples/cell/main.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ class ExampleHandler(IPythonHandler):
2424

2525
def get(self):
2626
"""Get the main page for the application's interface."""
27-
return self.write(self.render_template("index.html",
28-
static=self.static_url, base_url=self.base_url,
29-
token=self.settings['token']))
27+
return self.write(self.render_template('index.html',
28+
static=self.static_url,
29+
base_url=self.base_url,
30+
token=self.settings['token']))
3031

3132
def get_template(self, name):
3233
loader = FileSystemLoader(HERE)
@@ -44,9 +45,8 @@ def init_webapp(self):
4445
default_handlers = [
4546
(r'/example/?', ExampleHandler),
4647
(r"/example/(.*)", FileFindHandler,
47-
{'path': os.path.join(HERE, 'build')}),
48-
]
49-
self.web_app.add_handlers(".*$", default_handlers)
48+
{'path': os.path.join(HERE, 'build')}) ]
49+
self.web_app.add_handlers('.*$', default_handlers)
5050

5151

5252
if __name__ == '__main__':

examples/console/main.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ class ExampleHandler(IPythonHandler):
2424

2525
def get(self):
2626
"""Get the main page for the application's interface."""
27-
return self.write(self.render_template("index.html",
28-
static=self.static_url, base_url=self.base_url,
29-
token=self.settings['token']))
27+
return self.write(self.render_template('index.html',
28+
static=self.static_url,
29+
base_url=self.base_url,
30+
token=self.settings['token']))
3031

3132
def get_template(self, name):
3233
loader = FileSystemLoader(HERE)
@@ -44,9 +45,8 @@ def init_webapp(self):
4445
default_handlers = [
4546
(r'/example/?', ExampleHandler),
4647
(r"/example/(.*)", FileFindHandler,
47-
{'path': os.path.join(HERE, 'build')}),
48-
]
49-
self.web_app.add_handlers(".*$", default_handlers)
48+
{'path': os.path.join(HERE, 'build')}) ]
49+
self.web_app.add_handlers('.*$', default_handlers)
5050

5151

5252
if __name__ == '__main__':

examples/filebrowser/main.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ class ExampleHandler(IPythonHandler):
2424

2525
def get(self):
2626
"""Get the main page for the application's interface."""
27-
return self.write(self.render_template("index.html",
28-
static=self.static_url, base_url=self.base_url,
29-
token=self.settings['token']))
27+
return self.write(self.render_template('index.html',
28+
static=self.static_url,
29+
base_url=self.base_url,
30+
token=self.settings['token']))
3031

3132
def get_template(self, name):
3233
loader = FileSystemLoader(HERE)
@@ -44,9 +45,8 @@ def init_webapp(self):
4445
default_handlers = [
4546
(r'/example/?', ExampleHandler),
4647
(r"/example/(.*)", FileFindHandler,
47-
{'path': os.path.join(HERE, 'build')}),
48-
]
49-
self.web_app.add_handlers(".*$", default_handlers)
48+
{'path': os.path.join(HERE, 'build')}) ]
49+
self.web_app.add_handlers('.*$', default_handlers)
5050

5151

5252
if __name__ == '__main__':

examples/notebook/main.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ class ExampleHandler(IPythonHandler):
2424

2525
def get(self):
2626
"""Get the main page for the application's interface."""
27-
return self.write(self.render_template("index.html",
28-
static=self.static_url, base_url=self.base_url,
29-
token=self.settings['token']))
27+
return self.write(self.render_template('index.html',
28+
static=self.static_url,
29+
base_url=self.base_url,
30+
token=self.settings['token']))
3031

3132
def get_template(self, name):
3233
loader = FileSystemLoader(HERE)
@@ -44,9 +45,9 @@ def init_webapp(self):
4445
default_handlers = [
4546
(r'/example/?', ExampleHandler),
4647
(r"/example/(.*)", FileFindHandler,
47-
{'path': os.path.join(HERE, 'build')}),
48+
{'path': os.path.join(HERE, 'build')})
4849
]
49-
self.web_app.add_handlers(".*$", default_handlers)
50+
self.web_app.add_handlers('.*$', default_handlers)
5051

5152

5253
if __name__ == '__main__':

examples/terminal/main.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@ class ExampleHandler(IPythonHandler):
2424

2525
def get(self):
2626
"""Get the main page for the application's interface."""
27-
return self.write(self.render_template("index.html",
28-
static=self.static_url, base_url=self.base_url,
29-
token=self.settings['token'],
30-
terminals_available=self.settings['terminals_available']))
27+
available = self.settings['terminals_available']
28+
return self.write(self.render_template('index.html',
29+
static=self.static_url,
30+
base_url=self.base_url,
31+
token=self.settings['token'],
32+
terminals_available=available))
3133

3234
def get_template(self, name):
3335
loader = FileSystemLoader(HERE)
@@ -45,9 +47,9 @@ def init_webapp(self):
4547
default_handlers = [
4648
(r'/example/?', ExampleHandler),
4749
(r"/example/(.*)", FileFindHandler,
48-
{'path': os.path.join(HERE, 'build')}),
50+
{'path': os.path.join(HERE, 'build')})
4951
]
50-
self.web_app.add_handlers(".*$", default_handlers)
52+
self.web_app.add_handlers('.*$', default_handlers)
5153

5254

5355
if __name__ == '__main__':

jupyterlab/__init__.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
# Copyright (c) Jupyter Development Team.
44
# Distributed under the terms of the Modified BSD License.
55

6-
from ._version import __version__
7-
from .extension import load_jupyter_server_extension
6+
from ._version import __version__ # noqa
7+
from .extension import load_jupyter_server_extension # noqa
8+
89

910
def _jupyter_server_extension_paths():
10-
return [{
11-
"module": "jupyterlab"
12-
}]
11+
return [{'module': 'jupyterlab'}]

jupyterlab/chrome-test.js

+27-11
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,48 @@
11
const puppeteer = require('puppeteer');
2-
2+
const inspect = require('util').inspect;
33
const URL = process.argv[2];
44

55
async function main() {
66
console.info('Starting Chrome Headless');
77

88
const browser = await puppeteer.launch({ args: ['--no-sandbox'] });
99
const page = await browser.newPage();
10-
console.info('Navigating to page:', URL);
1110

11+
console.info('Navigating to page:', URL);
1212
await page.goto(URL);
13-
console.info('Waiting for application to start...');
14-
const res = await page.waitForSelector('#browserResult');
15-
const textContent = await res.getProperty('textContent');
13+
console.info('Waiting for page to load...');
14+
15+
const html = await page.content();
16+
if (inspect(html).indexOf('jupyter-config-data') === -1) {
17+
console.error('Error loading JupyterLab page:');
18+
console.error(html);
19+
}
20+
21+
const el = await page.waitForSelector('#browserTest', { timeout: 100000 });
22+
console.log('Waiting for application to start...');
23+
let testError = null;
24+
25+
try {
26+
await page.waitForSelector('.completed');
27+
} catch (e) {
28+
testError = e;
29+
}
30+
const textContent = await el.getProperty('textContent');
1631
const errors = JSON.parse(await textContent.jsonValue());
17-
await browser.close();
1832

1933
for (let error of errors) {
20-
console.error('got error', error);
21-
}
22-
if (errors.length !== 0) {
23-
throw 'Got some errors';
34+
console.error(`Parsed an error from text content: ${error.message}`, error);
2435
}
2536

37+
await browser.close();
38+
39+
if (testError) {
40+
throw testError;
41+
}
2642
console.info('Chrome test complete');
2743
}
2844

29-
// stop process if we raise an error in the async fynction
45+
// Stop the process if an error is raised in the async function.
3046
process.on('unhandledRejection', up => {
3147
throw up;
3248
});

jupyterlab/commands.py

+16-16
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ def ensure_dev(logger=None):
103103
for theme in theme_packages:
104104
base_path = pjoin(parent, 'packages', theme)
105105
if not osp.exists(pjoin(base_path, 'static')):
106-
yarn_proc = Process(['node', YARN_PATH, 'build:webpack'], cwd=base_path,
107-
logger=logger)
106+
yarn_proc = Process(['node', YARN_PATH, 'build:webpack'],
107+
cwd=base_path, logger=logger)
108108
yarn_proc.wait()
109109

110110
if not osp.exists(pjoin(parent, 'dev_mode', 'static')):
@@ -156,7 +156,7 @@ def watch_packages(logger=None):
156156
# Run typescript watch and wait for the string indicating it is done.
157157
ts_regex = r'.* Found 0 errors\. Watching for file changes\.'
158158
ts_proc = WatchHelper(['node', YARN_PATH, 'run', 'watch'],
159-
cwd=ts_dir, logger=logger, startup_regex=ts_regex)
159+
cwd=ts_dir, logger=logger, startup_regex=ts_regex)
160160

161161
# Run the metapackage file watcher.
162162
tsf_regex = 'Watching the metapackage files...'
@@ -184,8 +184,8 @@ def watch_dev(logger=None):
184184

185185
# Run webpack watch and wait for compilation.
186186
wp_proc = WatchHelper(['node', YARN_PATH, 'run', 'watch'],
187-
cwd=DEV_DIR, logger=logger,
188-
startup_regex=WEBPACK_EXPECT)
187+
cwd=DEV_DIR, logger=logger,
188+
startup_regex=WEBPACK_EXPECT)
189189

190190
return package_procs + [wp_proc]
191191

@@ -260,14 +260,14 @@ def clean(app_dir=None):
260260

261261

262262
def build(app_dir=None, name=None, version=None, public_url=None,
263-
logger=None, command='build:prod', kill_event=None,
264-
clean_staging=False):
263+
logger=None, command='build:prod', kill_event=None,
264+
clean_staging=False):
265265
"""Build the JupyterLab application.
266266
"""
267267
_node_check()
268268
handler = _AppHandler(app_dir, logger, kill_event=kill_event)
269269
return handler.build(name=name, version=version, public_url=public_url,
270-
command=command, clean_staging=clean_staging)
270+
command=command, clean_staging=clean_staging)
271271

272272

273273
def get_app_info(app_dir=None, logger=None):
@@ -430,7 +430,7 @@ def install_extension(self, extension, existing=None):
430430
return True
431431

432432
def build(self, name=None, version=None, public_url=None,
433-
command='build:prod', clean_staging=False):
433+
command='build:prod', clean_staging=False):
434434
"""Build the application.
435435
"""
436436
# Set up the build directory.
@@ -461,9 +461,9 @@ def watch(self):
461461
self._run(['node', YARN_PATH, 'install'], cwd=staging)
462462

463463
proc = WatchHelper(['node', YARN_PATH, 'run', 'watch'],
464-
cwd=pjoin(self.app_dir, 'staging'),
465-
startup_regex=WEBPACK_EXPECT,
466-
logger=self.logger)
464+
cwd=pjoin(self.app_dir, 'staging'),
465+
startup_regex=WEBPACK_EXPECT,
466+
logger=self.logger)
467467
return [proc]
468468

469469
def list_extensions(self):
@@ -659,7 +659,6 @@ def _update_extension(self, name):
659659
self.logger.info('Updating %s to version %s' % (name, latest))
660660
return self.install_extension('%s@%s' % (name, latest))
661661

662-
663662
def link_package(self, path):
664663
"""Link a package at the given path.
665664
@@ -781,7 +780,8 @@ def _check_common_extension(self, extension, info, check_installed_only):
781780

782781
errors = self._get_extension_compat()[extension]
783782
if errors:
784-
self.logger.info('%s:%s (compatibility errors)' % (extension, RED_X))
783+
self.logger.info('%s:%s (compatibility errors)' %
784+
(extension, RED_X))
785785
return False
786786

787787
if check_installed_only:
@@ -836,7 +836,7 @@ def _get_app_info(self):
836836
return info
837837

838838
def _populate_staging(self, name=None, version=None, public_url=None,
839-
clean=False):
839+
clean=False):
840840
"""Set up the assets in the staging directory.
841841
"""
842842
app_dir = self.app_dir
@@ -908,7 +908,7 @@ def _populate_staging(self, name=None, version=None, public_url=None,
908908
continue
909909
dname = pjoin(app_dir, 'extensions')
910910
self._update_local(key, source, dname, extensions[key],
911-
'local_extensions')
911+
'local_extensions')
912912

913913
# Update the list of local extensions if any were removed.
914914
if removed:

0 commit comments

Comments
 (0)