labextensions.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. # coding: utf-8
  2. """Jupyter LabExtension Entry Points."""
  3. # Copyright (c) Jupyter Development Team.
  4. # Distributed under the terms of the Modified BSD License.
  5. from __future__ import print_function
  6. import os
  7. import sys
  8. import traceback
  9. from copy import copy
  10. from jupyter_core.application import JupyterApp, base_flags, base_aliases
  11. from traitlets import Bool, Unicode
  12. from .commands import (
  13. install_extension, uninstall_extension, list_extensions,
  14. enable_extension, disable_extension, check_extension,
  15. link_package, unlink_package, build, get_app_version, HERE
  16. )
  17. flags = dict(base_flags)
  18. flags['no-build'] = (
  19. {'BaseExtensionApp': {'should_build': False}},
  20. "Defer building the app after the action."
  21. )
  22. flags['dev-build'] = (
  23. {'BaseExtensionApp': {'dev_build': True}},
  24. "Build in Development mode"
  25. )
  26. flags['clean'] = (
  27. {'BaseExtensionApp': {'should_clean': True}},
  28. "Cleanup intermediate files after the action."
  29. )
  30. check_flags = copy(flags)
  31. check_flags['installed'] = (
  32. {'CheckLabExtensionsApp': {'should_check_installed_only': True}},
  33. "Check only if the extension is installed."
  34. )
  35. aliases = dict(base_aliases)
  36. aliases['app-dir'] = 'BaseExtensionApp.app_dir'
  37. VERSION = get_app_version()
  38. class BaseExtensionApp(JupyterApp):
  39. version = VERSION
  40. flags = flags
  41. aliases = aliases
  42. app_dir = Unicode('', config=True,
  43. help="The app directory to target")
  44. should_build = Bool(True, config=True,
  45. help="Whether to build the app after the action")
  46. dev_build = Bool(False, config=True,
  47. help="Whether to build in dev mode (defaults to production mode)")
  48. should_clean = Bool(False, config=True,
  49. help="Whether temporary files should be cleaned up after building jupyterlab")
  50. def start(self):
  51. if self.app_dir and self.app_dir.startswith(HERE):
  52. raise ValueError('Cannot run lab extension commands in core app')
  53. try:
  54. ans = self.run_task()
  55. if ans and self.should_build:
  56. command = 'build:prod' if not self.dev_build else 'build'
  57. build(app_dir=self.app_dir, clean_staging=self.should_clean,
  58. logger=self.log, command=command)
  59. except Exception as ex:
  60. _, _, exc_traceback = sys.exc_info()
  61. msg = traceback.format_exception(ex.__class__, ex, exc_traceback)
  62. for line in msg:
  63. self.log.debug(line)
  64. self.log.error('\nErrored, use --debug for full output:')
  65. self.log.error(msg[-1].strip())
  66. sys.exit(1)
  67. def run_task(self):
  68. pass
  69. def _log_format_default(self):
  70. """A default format for messages"""
  71. return "%(message)s"
  72. class InstallLabExtensionApp(BaseExtensionApp):
  73. description = "Install labextension(s)"
  74. def run_task(self):
  75. self.extra_args = self.extra_args or [os.getcwd()]
  76. return any([
  77. install_extension(arg, self.app_dir, logger=self.log)
  78. for arg in self.extra_args
  79. ])
  80. class LinkLabExtensionApp(BaseExtensionApp):
  81. description = """
  82. Link local npm packages that are not lab extensions.
  83. Links a package to the JupyterLab build process. A linked
  84. package is manually re-installed from its source location when
  85. `jupyter lab build` is run.
  86. """
  87. should_build = Bool(True, config=True,
  88. help="Whether to build the app after the action")
  89. def run_task(self):
  90. self.extra_args = self.extra_args or [os.getcwd()]
  91. return any([
  92. link_package(arg, self.app_dir, logger=self.log)
  93. for arg in self.extra_args
  94. ])
  95. class UnlinkLabExtensionApp(BaseExtensionApp):
  96. description = "Unlink packages by name or path"
  97. def run_task(self):
  98. self.extra_args = self.extra_args or [os.getcwd()]
  99. return any([
  100. unlink_package(arg, self.app_dir, logger=self.log)
  101. for arg in self.extra_args
  102. ])
  103. class UninstallLabExtensionApp(BaseExtensionApp):
  104. description = "Uninstall labextension(s) by name"
  105. def run_task(self):
  106. self.extra_args = self.extra_args or [os.getcwd()]
  107. return any([
  108. uninstall_extension(arg, self.app_dir, logger=self.log)
  109. for arg in self.extra_args
  110. ])
  111. class ListLabExtensionsApp(BaseExtensionApp):
  112. description = "List the installed labextensions"
  113. def run_task(self):
  114. list_extensions(self.app_dir, logger=self.log)
  115. class EnableLabExtensionsApp(BaseExtensionApp):
  116. description = "Enable labextension(s) by name"
  117. def run_task(self):
  118. [enable_extension(arg, self.app_dir, logger=self.log)
  119. for arg in self.extra_args]
  120. class DisableLabExtensionsApp(BaseExtensionApp):
  121. description = "Disable labextension(s) by name"
  122. def run_task(self):
  123. [disable_extension(arg, self.app_dir, logger=self.log)
  124. for arg in self.extra_args]
  125. class CheckLabExtensionsApp(BaseExtensionApp):
  126. description = "Check labextension(s) by name"
  127. flags = check_flags
  128. should_check_installed_only = Bool(False, config=True,
  129. help="Whether it should check only if the extensions is installed")
  130. def run_task(self):
  131. all_enabled = all(
  132. check_extension(
  133. arg, self.app_dir,
  134. self.should_check_installed_only,
  135. logger=self.log)
  136. for arg in self.extra_args)
  137. if not all_enabled:
  138. exit(1)
  139. _examples = """
  140. jupyter labextension list # list all configured labextensions
  141. jupyter labextension install <extension name> # install a labextension
  142. jupyter labextension uninstall <extension name> # uninstall a labextension
  143. """
  144. class LabExtensionApp(JupyterApp):
  145. """Base jupyter labextension command entry point"""
  146. name = "jupyter labextension"
  147. version = VERSION
  148. description = "Work with JupyterLab extensions"
  149. examples = _examples
  150. subcommands = dict(
  151. install=(InstallLabExtensionApp, "Install labextension(s)"),
  152. uninstall=(UninstallLabExtensionApp, "Uninstall labextension(s)"),
  153. list=(ListLabExtensionsApp, "List labextensions"),
  154. link=(LinkLabExtensionApp, "Link labextension(s)"),
  155. unlink=(UnlinkLabExtensionApp, "Unlink labextension(s)"),
  156. enable=(EnableLabExtensionsApp, "Enable labextension(s)"),
  157. disable=(DisableLabExtensionsApp, "Disable labextension(s)"),
  158. check=(CheckLabExtensionsApp, "Check labextension(s)"),
  159. )
  160. def start(self):
  161. """Perform the App's functions as configured"""
  162. super(LabExtensionApp, self).start()
  163. # The above should have called a subcommand and raised NoStart; if we
  164. # get here, it didn't, so we should self.log.info a message.
  165. subcmds = ", ".join(sorted(self.subcommands))
  166. sys.exit("Please supply at least one subcommand: %s" % subcmds)
  167. main = LabExtensionApp.launch_instance