labextensions.py 7.7 KB

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