# coding: utf-8
"""Jupyter LabExtension Entry Points."""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
import os
import sys
import traceback
from copy import copy
from jupyter_core.application import JupyterApp, base_flags, base_aliases
from traitlets import Bool, Unicode
from .commands import (
install_extension, uninstall_extension, list_extensions,
enable_extension, disable_extension, check_extension,
link_package, unlink_package, build, get_app_version, HERE,
update_extension,
)
flags = dict(base_flags)
flags['no-build'] = (
{'BaseExtensionApp': {'should_build': False}},
"Defer building the app after the action."
)
flags['dev-build'] = (
{'BaseExtensionApp': {'dev_build': True}},
"Build in Development mode"
)
flags['clean'] = (
{'BaseExtensionApp': {'should_clean': True}},
"Cleanup intermediate files after the action."
)
check_flags = copy(flags)
check_flags['installed'] = (
{'CheckLabExtensionsApp': {'should_check_installed_only': True}},
"Check only if the extension is installed."
)
update_flags = copy(flags)
update_flags['all'] = (
{'UpdateLabExtensionApp': {'all': True}},
"Update all extensions"
)
aliases = dict(base_aliases)
aliases['app-dir'] = 'BaseExtensionApp.app_dir'
VERSION = get_app_version()
class BaseExtensionApp(JupyterApp):
version = VERSION
flags = flags
aliases = aliases
app_dir = Unicode('', config=True,
help="The app directory to target")
should_build = Bool(True, config=True,
help="Whether to build the app after the action")
dev_build = Bool(True, config=True,
help="Whether to build in dev mode (defaults to dev mode)")
should_clean = Bool(False, config=True,
help="Whether temporary files should be cleaned up after building jupyterlab")
def start(self):
if self.app_dir and self.app_dir.startswith(HERE):
raise ValueError('Cannot run lab extension commands in core app')
try:
ans = self.run_task()
if ans and self.should_build:
command = 'build:prod' if not self.dev_build else 'build'
build(app_dir=self.app_dir, clean_staging=self.should_clean,
logger=self.log, command=command)
except Exception as ex:
_, _, exc_traceback = sys.exc_info()
msg = traceback.format_exception(ex.__class__, ex, exc_traceback)
for line in msg:
self.log.debug(line)
self.log.error('\nErrored, use --debug for full output:')
self.log.error(msg[-1].strip())
sys.exit(1)
def run_task(self):
pass
def _log_format_default(self):
"""A default format for messages"""
return "%(message)s"
class InstallLabExtensionApp(BaseExtensionApp):
description = "Install labextension(s)"
def run_task(self):
self.extra_args = self.extra_args or [os.getcwd()]
return any([
install_extension(arg, self.app_dir, logger=self.log)
for arg in self.extra_args
])
class UpdateLabExtensionApp(BaseExtensionApp):
description = "Update labextension(s)"
flags = update_flags
all = Bool(False, config=True,
help="Whether to update all extensions")
def run_task(self):
if not self.all and not self.extra_args:
self.log.warn('Specify an extension to update, or use --all to update all extensions')
return False
if self.all:
return update_extension(all_=True, app_dir=self.app_dir, logger=self.log)
return any([
update_extension(name=arg, app_dir=self.app_dir, logger=self.log)
for arg in self.extra_args
])
class LinkLabExtensionApp(BaseExtensionApp):
description = """
Link local npm packages that are not lab extensions.
Links a package to the JupyterLab build process. A linked
package is manually re-installed from its source location when
`jupyter lab build` is run.
"""
should_build = Bool(True, config=True,
help="Whether to build the app after the action")
def run_task(self):
self.extra_args = self.extra_args or [os.getcwd()]
return any([
link_package(arg, self.app_dir, logger=self.log)
for arg in self.extra_args
])
class UnlinkLabExtensionApp(BaseExtensionApp):
description = "Unlink packages by name or path"
def run_task(self):
self.extra_args = self.extra_args or [os.getcwd()]
return any([
unlink_package(arg, self.app_dir, logger=self.log)
for arg in self.extra_args
])
class UninstallLabExtensionApp(BaseExtensionApp):
description = "Uninstall labextension(s) by name"
def run_task(self):
self.extra_args = self.extra_args or [os.getcwd()]
return any([
uninstall_extension(arg, self.app_dir, logger=self.log)
for arg in self.extra_args
])
class ListLabExtensionsApp(BaseExtensionApp):
description = "List the installed labextensions"
def run_task(self):
list_extensions(self.app_dir, logger=self.log)
class EnableLabExtensionsApp(BaseExtensionApp):
description = "Enable labextension(s) by name"
def run_task(self):
[enable_extension(arg, self.app_dir, logger=self.log)
for arg in self.extra_args]
class DisableLabExtensionsApp(BaseExtensionApp):
description = "Disable labextension(s) by name"
def run_task(self):
[disable_extension(arg, self.app_dir, logger=self.log)
for arg in self.extra_args]
class CheckLabExtensionsApp(BaseExtensionApp):
description = "Check labextension(s) by name"
flags = check_flags
should_check_installed_only = Bool(False, config=True,
help="Whether it should check only if the extensions is installed")
def run_task(self):
all_enabled = all(
check_extension(
arg, self.app_dir,
self.should_check_installed_only,
logger=self.log)
for arg in self.extra_args)
if not all_enabled:
exit(1)
_examples = """
jupyter labextension list # list all configured labextensions
jupyter labextension install <extension name> # install a labextension
jupyter labextension uninstall <extension name> # uninstall a labextension
"""
class LabExtensionApp(JupyterApp):
"""Base jupyter labextension command entry point"""
name = "jupyter labextension"
version = VERSION
description = "Work with JupyterLab extensions"
examples = _examples
subcommands = dict(
install=(InstallLabExtensionApp, "Install labextension(s)"),
update=(UpdateLabExtensionApp, "Update labextension(s)"),
uninstall=(UninstallLabExtensionApp, "Uninstall labextension(s)"),
list=(ListLabExtensionsApp, "List labextensions"),
link=(LinkLabExtensionApp, "Link labextension(s)"),
unlink=(UnlinkLabExtensionApp, "Unlink labextension(s)"),
enable=(EnableLabExtensionsApp, "Enable labextension(s)"),
disable=(DisableLabExtensionsApp, "Disable labextension(s)"),
check=(CheckLabExtensionsApp, "Check labextension(s)"),
)
def start(self):
"""Perform the App's functions as configured"""
super(LabExtensionApp, self).start()
# The above should have called a subcommand and raised NoStart; if we
# get here, it didn't, so we should self.log.info a message.
subcmds = ", ".join(sorted(self.subcommands))
sys.exit("Please supply at least one subcommand: %s" % subcmds)
main = LabExtensionApp.launch_instance
if __name__ == '__main__':
sys.exit(main())