Extension Migration Guide#
JupyterLab 4.1 to 4.2#
API updates#
The
CodeEditor.ICoordinate
interface was corrected to not includetoJSON()
,x
,y
,width
andheight
; these properties were never set by methods returningICoordinate
and they were never used by methods accepting it.CodeEditor.getCoordinateForPosition
return type was corrected to clarify that it can returnnull
; previouslynull
could be returned despite the return type indicating it would always return a non-nullICoordinate
value.The commands
workspace-ui:save
andworkspace-ui:save-as
were moved from the@jupyterlab/apputils-extension:workspaces
plugin to a new dedicated@jupyterlab/workspaces-extension
package and can be explicitly required by requesting theIWorkspaceCommands
token. This token is by default provided by the new@jupyterlab/workspaces-extension:commands
plugin. The@jupyterlab/apputils-extension:workspaces
plugin now only defines the workspace MIME type renderer used to open files with.jupyterlab-workspace
extension as JupyterLab workspaces.The cell toolbar node has been moved from the cell node to the cell input node. Therefore the parent of the cell toolbar has changed and can not be used directly to retrieve the corresponding cell node anymore.
Shortcuts extension rework#
The @jupyterlab/shortcuts-extension
package was reworked to fix multiple bugs and increase type safety.
While this package does not expose any programmatic APIs, and changes to the theming were minimal,
the major version of the package was increased to 5.0 to reflect the extend of the changes.
No action is required from extension authors (unless you used non-public components from /lib), however the authors of applications built on top of JupyterLab components are encouraged to upgrade to this new version as it can significantly improve the user experience.
JupyterLab 4.0 to 4.1#
Plugin manager and extension locks#
Prior to JupyterLab 4.1 there was no mechanisms: - for users to disable/enable individual plugins (rather than entire extensions) - for administrators to fully block users from enabling/disabling certain extensions
This version of JupyterLab enables both with the addition of Plugin Manager.
If your installation had any plugins disabled these will be automatically locked
on the first startup to ensure that there is no change to user-exposed functionality. The plugin manager
itself can be disabled and locked using jupyter labextension
commands, but we recommend to instead
lock individual plugins as required.
If your extension previously included a custom enable/disable setting, you may be able to replace it with instructions pointing users to the Plugin Manager. However, please consider whether your extension may be used in distributions which do not include Plugin Manager or have it disabled.
CSS class name change in the WindowedList
superclass of StaticNotebook
#
The class
.jp-WindowedPanel-window
has been renamed to.jp-WindowedPanel-viewport
.The notebook scroll container is now
.jp-WindowedPanel-outer
rather than.jp-Notebook
Galata notebook helpers getCell and getCellCount were updated accordingly
Change of notebook focus handling impacting command-mode shortcut selectors#
Previously, focus in the notebook would revert to the notebook HTML node when switching to command mode, which was preventing Tab navigation between cells, especially impacting users with accessibility needs. In JupyterLab 4.1+ the focus stays on the active cell when switching to command mode; this requires all shortcut selectors to be adjusted as follows:
.jp-Notebook:focus.jp-mod-commandMode
,.jp-Notebook:focus
, and[data-jp-traversable]:focus
should be replaced with: -.jp-Notebook.jp-mod-commandMode :focus:not(:read-write)
for JupyterLab 4.1.0+ -.jp-Notebook.jp-mod-commandMode:not(.jp-mod-readWrite) :focus
for JupyterLab 4.1.1+[data-jp-kernel-user]:focus
should be replaced with: -[data-jp-kernel-user] :focus:not(:read-write)
for JupyterLab 4.1.0+ -[data-jp-kernel-user]:not(.jp-mod-readWrite) :focus:not(:read-write)
for JupyterLab 4.1.1+
Please note that :not(:read-write)
fragment disables shortcuts
when text fields (such as cell editor) are focused to avoid intercepting
characters typed by the user into the text fields, however if your shortcut
does not correspond to any key/typographic character (e.g. most shortcuts
with Ctrl modifier) you may prefer to drop this fragment
if you want the shortcut to be active in text fields.
Further, JupyterLab 4.1.1 introduced indicator class .jp-mod-readWrite
that is applied to the notebook node when the active element accepts
keyboard input as defined by :read-write
selector. This indicator
class is required to detect :read-write
elements which are nested
within an open shadow DOM (such as Panel framework widgets).
If your framework uses a closed shadow DOM, or expects keyboard
interactions on elements that are not recognised as editable by browser
heuristics of :read-write
selector, you need to set a data attribute
lm-suppress-shortcuts on the outer host element to suppress shortcuts.
To prevent breaking the user experience these changes are made transparently in the background, but will emit a warning and extension developers should make the change at the source before the next major JupyterLab release.
Visibility of StatusBar
elements at high magnifications#
Statusbar items are now hidden by default at high magnification/low resolution to prevent overlap for those using the application at high magnifications.
An additional
priority
property has been added to the options ofIStatusBar.registerStatusItem
method to allow the status bar item to remain visible; the intended usage is for small statusbar items that either add functionality that would be particularly useful at high zoom or is inaccessible otherwise.
JupyterLab 3.x to 4.x#
Because of significant type changes from JupyterLab 3.x to 4.x, we recommend publishing a new major version of your extension to work with each major version of JupyterLab. For examples of extensions that use different major versions for Lab 3 and Lab 4, see jupyterlab-vim and jupyter-ai.
Upgrading extension using the upgrade script#
JupyterLab 4.x provides a script to upgrade an existing extension to use the new extension system and packaging.
Note
Back up your extension - the best if you use a version control like git, is to work on a new branch.
First, make sure to update to JupyterLab 4 and install copier
and some dependencies. With pip
:
pip install -U jupyterlab[upgrade-extension]
Or with conda
:
conda install -c conda-forge jupyterlab=4 "copier=9" jinja2-time
Then at the root folder of the extension, run:
python -m jupyterlab.upgrade_extension .
The upgrade script creates the necessary files for packaging the JupyterLab extension as a Python package.
The script will ask you for all files if you want to override them or not. By default the configuration files
will be overridden for the newer version. In particular, if you were using Python setuptools (aka setup.py
and/or setup.cfg
), you will like need to update the pyproject.toml
file (see
PEP example).
The upgrade script also updates the dependencies in package.json
to the ^4.0.0
packages.
For more details about the new file structure and packaging of the extension, check out the extension tutorial: Extension Tutorial
Note
You will need to modify the code of your extension if it is impacted by the API changes mentioned below.
jlpm#
The utility jlpm
uses Yarn 3 (previously Yarn 1). This will require updating your
package configuration.
Create a file
.yarnrc.yml
containing:
enableImmutableInstalls: false
nodeLinker: node-modules
Add to
.gitignore
.yarn/
Run
jlpm install
This will reset youryarn.lock
content as its format has changed.
Note
You can find more information on upgrading Yarn from version 1 to version 3 in Yarn documentation.
If you are hit by multiple versions of the same packages (like @lumino/widgets
),
TypeScript may complain that the types are not matching. One possible solution
is to force packages deduplication using:
jlpm dlx yarn-berry-deduplicate
API breaking changes#
Note
With JupyterLab 4.x, the npm package version policy changed to not bump major version with the Python package unless required to ease extension compatibility.
Here is a list of JupyterLab npm packages that encountered API changes and therefore have
bumped their major version (following semver convention). We want to point out particularly
@jupyterlab/documentsearch
and @jupyterlab/toc
API that have been fully reworked.
@jupyterlab/application
from 3.x to 4.xMajor version bump to allow alternate
ServiceManager
implementations inJupyterFrontEnd
. Specifically this allows the use of a mock manager. This also makes theJupyterLab.IOptions
more permissive to not require a shell when options are given and allow a shell that meets theILabShell
interface. As a consequence, all other@jupyterlab/
packages have their major version bumped too. See jupyterlab/jupyterlab#11537 for more details.Rename token
@jupyterlab/apputils:IConnectionLost
to@jupyterlab/application:IConnectionLost
.
@jupyterlab/apputils
from 3.x to 4.xRename
IToolbarWidgetRegistry.registerFactory
toIToolbarWidgetRegistry.addFactory
ISanitizer
andISanitizer.IOptions
are deprecated in favor ofIRenderMime.ISanitizer
andIRenderMime.ISanitizerOptions
in@jupyterlab/rendermime-interfaces
.Global
sessionContextDialogs
is removed; you should request the tokenISessionContextDialogs
(from@jupyterlab/apputils
).
@jupyterlab/attachments
from 3.x to 4.xRemoved
modelDB
fromIAttachmentsModel.IOptions
.
@jupyterlab/buildutils
from 3.x to 4.xThe
create-theme
script has been removed. If you want to create a new theme extension, you should use the TypeScript extension template (choosingtheme
askind
) instead.The
add-sibling
script has been removed. Check out Development workflow for source extensions instead.The
exitOnUuncaughtException
util function has been renamed toexitOnUncaughtException
(typo fix).
@jupyterlab/cells
from 3.x to 4.xMarkdownCell.toggleCollapsedSignal
renamedMarkdownCell.headingCollapsedChanged
To support notebook windowing, cell widget children (e.g. the editor or the output area) are not instantiated when the cell is attached to the notebook. You can test forisPlaceholder()
to see if the cell has been fully instantiated or wait for the promiseready
to be resolved. Additionally an attributeinViewport
and a signalinViewportChanged
are available to test if the cell is attached to the DOM. If you instantiate standalone cells outside of a notebook, you will probably need to set the constructor optionplaceholder
tofalse
to ensure direct rendering of the cell.InputArea.defaultContentFactory
andCell.defaultContentFactory
have been removed. If you need it, you can request the tokenIEditorServices
from@jupyterlab/codeeditor
. Then you can usenew Cell.ContentFactory({ editorFactory: token.factoryService.newInlineEditor });
.
@jupyterlab/celltags
from 3.x to 4.0 The@jupyterlab/celltags
package has been removed and replaced by a widget in@jupyterlab/celltags-extension
. This widget is now rendered using@jupyterlab/metadataform
.@jupyterlab/codeeditor
from 3.x to 4.0CodeEditor.IEditor
has changed:resizeToFit()
is removedaddKeydownHandler()
is removed - you should add a CodeMirror extensionEditorView.domEventHandlers
withPrec.high
(to ensure it is not captured by keyboard shortcuts).
injectExtension()
added as experimental to inject a CodeMirror extension - you should prefer registeringnew extensions with
IEditorExtensionRegistry
.
CodeEditor.IOptions
has two new optional attributes:extensions?: Extensions[]
to provide custom extensions at editor instantiationinline?: boolean
whether the editor is a subpart of a document (like the notebook) or not.
CodeEditorWrapper.IOptions
has changed to{ factory, model, editorOptions }
.CodeViewerWidget.IOptions
has changed to{ factory, model, editorOptions }
.
@jupyterlab/codemirror
from 3.x to 4.0- Configuration parameters changes:
fontFamily
,fontSize
andlineHeight
: grouped in a subdictionnarycustomStyles
.insertSpaces
: changed forindentUnit
that can take a value within [‘Tab’, ‘1’, ‘2’, ‘4’, ‘8’]lineWrap
: changed - it is now a boolean.showTrailingSpace
: renamedhighlightTrailingWhitespace
coverGutterNextToScrollbar
: removedelectricChars
: removedextraKeys
: removed - you should register new keymap using the CodeMirror extensionkeymap.of(KeyBinding[])
handlePaste
: removedkeymap
: removedlineSeparator
: removed - Line separator are normalized to\n
lineWiseCopyCut
: removed - this is the default behaviorscrollbarStyle
: removedstyleSelectedText
: removedselectionPointer
: removedwordWrapColumn
: removed
Mode
has been removed. You can instead request the tokenIEditorLanguageHandler
. That provides similar API: -Mode.registerModeInfo
->IEditorLanguageHandler.addLanguage
-Mode.ensure()
->IEditorLanguageHandler.getLanguage()
-Mode.modeList
->IEditorLanguageHandler.getLanguages()
-Mode.run()
->IEditorLanguageHandler.highlight()
-Mode.findBest()
->IEditorLanguageHandler.findBest()
-Mode.findByName()
->IEditorLanguageHandler.findByName()
-Mode.findByMIME()
->IEditorLanguageHandler.findByMIME()
-Mode.findByExtension()
->IEditorLanguageHandler.findByExtension()
EditorSyntaxStatus
moved to@jupyterlab/fileeditor
@jupyterlab/codemirror-extension
from 3.x to 4.0Moved commands: -
codemirror:change-theme
->fileeditor:change-theme
(moved to@juptyerlab/fileeditor-extension
) -codemirror:change-mode
->fileeditor:change-language
(moved to@juptyerlab/fileeditor-extension
) -codemirror:find
->fileeditor:find
(moved to@juptyerlab/fileeditor-extension
) -codemirror:go-to-line
->fileeditor:go-to-line
(moved to@juptyerlab/fileeditor-extension
)Removed command:
codemirror:change-keymap
Moved plugins: -
@jupyterlab/codemirror-extension:commands
integrated within@jupyterlab/fileeditor-extension:plugin
-@jupyterlab/codemirror-extension:editor-syntax-status
->@jupyterlab/fileeditor-extension:editor-syntax-status
-@jupyterlab/codemirror-extension:editor-syntax-status
->@jupyterlab/fileeditor-extension:editor-syntax-status
@jupyterlab/completer
from 3.x to 4.xMajor version was bumped following major refactor aimed at performance improvements and enabling easier third-party integration.
- Adding custom completion suggestions (items):
In 3.x and earlier adding custom completion items required re-registering the completer connector for each file/cell using
register
method of old manager provided byICompletionManager
token; in 4.x this token and associatedICompletableAttributes
interface was removed and a proper method of registering a custom source of completions (a provider of completions) was added. To create a completer provider for JupyterLab, users need to implement theICompletionProvider
interface and then register this provider withICompletionProviderManager
token.In 3.x merging completions from different sources had to be performed by creating a connector internally merging results from other connectors. in 4.x
IProviderReconciliator
is used to merge completions from multiple providers, and can be customised in constructor for custom completion handlers (CompletionHandler
); customizing reconciliator in JupyterLab-managed completers is not yet possible.
- Rendering with
Completer.IRenderer
: In 3.x it was not possible to easily swap the renderer of JupyterLab-managed completers. In 4.x the renderer from the completion provider with highest rank is now used for all JupyterLab-managed completers. This behaviour is subject to revision in the future (please leave feedback).
Completer box is now using delayed rendering for off-screen content to improve time to first paint for top suggestions. To position the completer without rendering all items we search for the widest item using heuristic which can be adjusted in custom renderers (
itemWidthHeuristic
).The documentation panel now implements a loading indicator (a progress bar) customizable via optional
createLoadingDocsIndicator
renderer method.createItemNode
was removed in favour ofcreateCompletionItemNode
which is now required.createCompletionItemNode
is no longer responsible for sanitization of labels which is now a responsibility of the model (see below).
- Rendering with
- Model:
In 3.x it was not possible to easily swap the model of JupyterLab-managed completers. In 4.x the model factory from the completion provider with highest rank is now used for JupyterLab-managed completers. This behaviour is subject to revision in the future (please leave feedback).
Old methods for updating and accessing the completion items:
setOptions
,options
, anditems
were removed in favour ofcompletionItems
andsetCompletionItems
which are now required members ofCompleter.IModel
.New signal
queryChanged
was added and has to be emitted by models.Model is now responsible for sanitization of labels and preserving original label on
insertText
attribute (if not already defined); this change was required to properly handle escaping of HTML tags.
@jupyterlab/codeeditor
from 3.x to 4.xRemove
ISelectionStyle
(and thereforedefaultSelectionStyle
andIEditor.selectionStyle
). This was envisaged for real-time collaboration. But this is not used in the final implementation.
@jupyterlab/console
from 3.x to 4.xThe type of
IConsoleHistory.sessionContext
has been updated toISessionContext | null
instead ofISessionContext
. This might break the compilation of plugins accessing thesessionContext
from aConsoleHistory
, in particular those with the strict null checks enabled.
@jupyterlab/coreutils
from 3.x to 4.xThe
Time
namespace does not use themoment
library anymore for managing dates. Instead it switched to using theIntl
API now available in modern web browsers. TheTime.format
function is still available but does not accept thetimeFormat
argument anymore.
@jupyterlab/debugger
from 3.x to 4.xThe command
debugger:pause
command ID has been renameddebugger:pause-on-exceptions
to avoid ambiguity with pausing the current running thread.
@jupyterlab/docmanager
from 3.x to 4.xThe
renameDialog
now receives theDocumentRegistry.Context
instead of a path.The interface
DocumentManager.IWidgetOpener
is nowIDocumentWidgetOpener
and is provided by a new plugin@jupyterlab/docmanager-extension:opener
. TheIDocumentWidgetOpener
interface also now defines an`opened`
signal that is emitted when a widget is opened.Removed the property
docProviderFactory
from the interfaceDocumentManager.IOptions
.
@jupyterlab/docregister
from 3.x to 4.xTextModelFactory.preferredLanguage(path: string)
will always return''
. The editor languages is not available globally to provided it. You can recover the feature if needed, by requesting the tokenIEditorLanguageHandler
from@jupyterlab/codemirror
. Then you can usetoken.findByFileName(widget.context.path)?.name ?? ''
.
@jupyterlab/docprovider
from 3.x to 4.xThis package is no longer present in JupyterLab. For documentation related to Real-Time Collaboration, please check out RTC’s documentation
@jupyterlab/docregistry
from 3.x to 4.xRemoved the property
docProviderFactory
from the interfaceContext.IOptions
.The constructor of the class
DocumentModel
receives a parameterDocumentModel.IOptions
.The method
IModelFactory.createNew
receives a parameterDocumentRegistry.IModelOptions
.The method
TextModelFactory.createNew
receives a parameterDocumentModel.IOptions
.
@jupyterlab/documentsearch
from 3.x to 4.x@jupyterlab/documentsearch:plugin
has been renamed to@jupyterlab/documentsearch-extension:plugin
@jupyterlab/documentsearch:labShellWidgetListener
has been renamed to@jupyterlab/documentsearch-extension:labShellWidgetListener
This may impact application configuration (for instance if the plugin was disabled). The search provider API has been fully reworked. But the logic is similar, for new type of documents you will need to register a
ISearchProviderFactory
to theISearchProviderRegistry
. The factory will build aISearchProvider
for the document widget.
@jupyterlab/extensionmanager
from 3.x to 4.xThe frontend API has been drastically reduced to fetch all information from the backend. It is now advised that you implement a custom
ExtensionManager
class for your needs rather than overriding the frontend plugins. Seejupyterlab/extensions/pypi.py
for an example using PyPI.org and pip. You can then register your manager by defining an entry point in the Python package; seepyproject.toml::project.entry-points."jupyterlab.extension_manager_v1"
.
@jupyterlab/fileeditor
from 3.x to 4.xRemove the class
FileEditorCodeWrapper
, instead, you can useCodeEditorWrapper
from@jupyterlab/codeeditor
.
@jupyterlab/filebrowser
from 3.x to 4.xRemove the property
defaultBrowser
from the interfaceIFileBrowserFactory
. The default browser is now provided by it own plugin by requiring the tokenIDefaultFileBrowser
.Remove the
useFuzzyFilter
setter from theFileBrowser
class.
@jupyterlab/filebrowser-extension
from 3.x to 4.xRemove command
filebrowser:create-main-launcher
. You can replace bylauncher:create
(same behavior) All launcher creation actions are moved to@jupyterlab/launcher-extension
.
@jupyterlab/imageviewer-extension
from 3.x to 4.xRemoved
addCommands
from public API
@jupyterlab/mainmenu
from 3.x to 4.xIMainMenu.addMenu
signature changed fromaddMenu(menu: Menu, options?: IMainMenu.IAddOptions): void
toaddMenu(menu: Menu, update?: boolean, options?: IMainMenu.IAddOptions): void
Removed
createEditMenu
,createFileMenu
,createKernelMenu
,createViewMenu
,createRunMenu
,createTabsMenu
,createHelpMenu
from public API.
@jupyterlab/notebook
from 3.x to 4.xNotebookWidgetFactory.IOptions
has nosessionDialogs
option any more.The
NotebookPanel._onSave
method is nowprivate
.NotebookActions.collapseAll
method renamed toNotebookActions.collapseAllHeadings
.Command
Collapsible_Headings:Toggle_Collapse
renamed tonotebook:toggle-heading-collapse
.Command
Collapsible_Headings:Collapse_All
renamed tonotebook:collapse-all-headings
.Command
Collapsible_Headings:Expand_All
renamed tonotebook:expand-all-headings
.To support windowing, a new method
scrollToItem(index, behavior)
is available to scroll to any cell that may or may not be in the DOM. And newcellInViewportChanged
signal is available to listen for cells entering or leaving the viewport (in windowing mode). AndscrollToCell(cell)
is now returning aPromise<void>
calling internallyscrollToItem
.fullyRendered
,placeholderCellRendered
andremainingCellToRenderCount
have been removed. The defer rendering mode still exists. It will render some cells during spare CPU Idle time.Settings
numberCellsToRenderDirectly
,remainingTimeBeforeRescheduling
,renderCellOnIdle
,observedTopMargin
andobservedBottomMargin
have been removed. Instead awindowingMode
with value of defer, full or none andoverscanCount
have been added to manage the rendering mode.Added the property
sharedModel
to the interfaceNotebookModel.IOptions
.The method
NotebookModelFactory.createNew
receives a parameterNotebookModelFactory.IModelOptions
.The default Notebook toolbar’s
restart-and-run
button now refers to the commandnotebook:restart-run-all
instead ofrunmenu:restart-and-run-all
.StaticNotebook.defaultContentFactory
has been removed. If you need it, you can request the tokenIEditorServices
from@jupyterlab/codeeditor
. You can obtain it by requestednew NotebookPanel.ContentFactory({ editorFactory: token.factoryService.newInlineEditor });
notebooktools
module does not provides anymore theActiveCellTool
, theNotebookMetadataEditorTool
and theCellMetadataEditorTool
. All these widget are replaced by widgets in@jupyterlab/notebook-extension
, and are rendered using@jupyterlab/metadataform
. TheKeySelector
has also been removed as not used anymore, replaced by the use of@jupyterlab/metadataform
to provides selection for metadata keys.
@jupyterlab/rendermime
from 3.x to 4.xThe markdown parser has been extracted to its own plugin
@jupyterlab/markedparser-extension:plugin
that provides a new tokenIMarkdownParser
(defined in@jupyterlab/rendermime
). Consequently theIRendererFactory.createRenderer
has a new optionmarkdownParser
.[Not breaking]
IRenderMime.IExtension
has a new optionaldescription: string
attribute for documentation.
@jupyterlab/rendermime-interfaces
from 3.x to 4.x RemoveIRenderMime.IRenderer.translator?
attribute; the translator object is still passed to the constructor if needed by the renderer factory.@jupyterlab/services
from 6.x to 7.xRemove
Contents.IDrive.modelDBFactory
andContents.IManager.getModelDBFactory
.Added
Contents.IDrive.sharedModelFactory
andContents.IManager.getsharedModelFactory
.
@jupyterlab/shared-models
from 3.x to 4.xThis package is no longer present in JupyterLab. For documentation related to the shared models, please check out @jupyter/ydoc documentation.
@jupyterlab/statusbar
from 3.x to 4.xSetting
@jupyterlab/statusbar-extension:plugin . startMode
moved to@jupyterlab/application-extension:shell . startMode
Plugin
@jupyterlab/statusbar-extension:mode-switch
renamed to@jupyterlab/application-extension:mode-switch
Plugin
@jupyterlab/statusbar-extension:kernel-status
renamed to@jupyterlab/apputils-extension:kernel-status
Plugin
@jupyterlab/statusbar-extension:running-sessions-status
renamed to@jupyterlab/apputils-extension:running-sessions-status
Plugin
@jupyterlab/statusbar-extension:line-col-status
renamed to@jupyterlab/codemirror-extension:line-col-status
HoverBox
component moved from@jupyterlab/apputils
to@jupyterlab/ui-components
.Removed
STATUSBAR_PLUGIN_ID
from public API.
@jupyterlab/terminal
from 3.x to 4.xXterm.js upgraded from 4.x to 5.x
IThemeObject.selection
renamed toselectionBackground
@jupyterlab/terminal-extension
from 3.x to 4.xRemoved
addCommands
from public API
@jupyterlab/toc
from 3.x to 4.x@jupyterlab/toc:plugin
renamed@jupyterlab/toc-extension:registry
This may impact application configuration (for instance if the plugin was disabled). The namespaceTableOfContentsRegistry
has been renamedTableOfContents
. The API has been fully reworked. The new table of content providers must implement a factoryTableOfContents.IFactory
that will create a modelTableOfContents.IModel<TableOfContents.IHeading>
for supported widget. The model provides a list of headings described by atext
and alevel
and optionally aprefix
, acollapsed
state and adataset
(data DOM attributes dictionary).
@jupyterlab/ui-components
from 3.x to 4.xMajor version bumped following removal of Blueprint JS dependency. Extensions using proxied components like
Checkbox
,Select
orIntent
will need to import them explicitly from Blueprint JS library. Extensions usingButton
,Collapse
orInputGroup
may need to switch to the Blueprint components as the interfaces of those components in JupyterLab do not match those of Blueprint JS.Remove
Collapse
React component.- Form component registry changes:
Rename the plugin
'@jupyterlab/ui-components-extension:form-component-registry'
to'@jupyterlab/ui-components-extension:form-renderer-registry'
Rename the
IFormComponentRegistry
token toIFormRendererRegistry
, from@jupyterlab/ui-components:ISettingEditorRegistry
to@jupyterlab/ui-components:IFormRendererRegistry
.The
FormRendererRegistry
registersIFormRenderer
instead ofField
renderers. AIFormRenderer
defines afieldRenderer
(this is the renderer to set for backward compatibility) or awidgetRenderer
. The renderer id must follow the convention<ISettingRegistry.IPlugin.id>.<propertyName>
. This is to ensure a custom renderer is not used for property with the same name but different schema.
@jupyterlab/translation
from 3.x to 4.x Renamed the methodlocale
into the propertylanguageCode
in theNullTranslator
@jupyterlab/vdom
and@jupyterlab/vdom-extension
have been removed. The underlying vdom Python package is unmaintained. So it was decided to drop it from core packages.jupyter.extensions.hub-extension
from 3.x to 4.xRenamed
jupyter.extensions.hub-extension
to@jupyterlab/hub-extension:plugin
.Renamed
jupyter.extensions.hub-extension:plugin
to@jupyterlab/hub-extension:menu
.
TypeScript 5.0 update As a result of the update to TypeScript 5.0, a couple of interfaces have had their definitions changed. The
anchor
parameter ofHoverBox.IOptions
is now aDOMRect
instead ofClientRect
. TheCodeEditor.ICoordinate
interface now extendsDOMRectReadOnly
instead ofJSONObject, ClientRect
.React 18.2.0 update The update to React 18.2.0 (from 17.0.1) should be propagated to extensions as well. Here is the documentation about the migration to react 18.
Testing with Jest#
Jest has been updated to 29.2.0 (and ts-jest to 29.0.0). And therefore the jest configuration provided by
@jupyterlab/testutils
is compatible for that version. In particular:
The unmaintained reporter
jest-summary-reporter
has been replaced by the new defaultgithub-actions
reporter.The helper
flakyIt
has been removed. You can use the new jest.retryTimes instead.
With JupyterLab 4, we fixed circular dependencies due to the testutils
package. So it is now only a facade to export
helpers from various core packages. The exported helpers are the same as before expect for:
NBTestUtils.DEFAULT_CONTENT
: Removed - you could imported from@jupyterlab/notebook/lib/testutils
but we strongly advice not to and to use your own test data.NBTestUtils.DEFAULT_CONTENT_45
: Removed
Testing with Galata#
The in-page helpers are now in an JupyterLab extension to live in the common Webpack shared scoped. That new extension
is contained in the JupyterLab python package at jupyterlab.galata
. It requires to update your Jupyter server
configuration by adding the following line:
import jupyterlab
c.LabApp.extra_labextensions_path = str(Path(jupyterlab.__file__).parent / "galata")
Note
To ease configuration, we have introduce a new helper function jupyterlab.galata.configure_jupyter_server
. So you can
simplify the server configuration to be jupyterlab.galata.configure_jupyter_server(c)
.
- Here are the changes in the Javascript package
@jupyterlab/galata
from 4.x to 5.x: ContentsHelper
andgalata.newContentsHelper
have new constructor arguments to use Playwright API request object:new ContentsHelper(baseURL, page?, request?)
->new ContentsHelper(request?, page?)
galata.newContentsHelper(baseURL, page?, request?)
->galata.newContentsHelper(request?, page?)
you need to providerequest
orpage
; they both are fixtures provided by Playwright.galata.Mock.clearRunners(baseURL, runners, type)
->galata.Mock.clearRunners(request, runners, type)
In-pages helpers are now in an extension define in
jupyterlab/galata/extension
and store in@jupyterlab/galata/lib/extension
. And the global object has been renamedwindow.galata
instead ofwindow.galataip
(it still exists but it is deprecated).
Deprecated code removed#
The following deprecated API’s have been removed:
@jupyterlab/csvviewer
:CSVDelimiter.delimiterChanged
has been removed - dead code. You can directly access the delimiter from theCSVViewer
widget.@jupyterlab/mainmenu
:IJupyterLabMenu
andJupyterLabMenu
have been removed. You can use directlyIRankedMenu
andRankedMenu
from@jupyterlab/ui-components
@jupyterlab/notebook
:NotebookWidgetFactory
default toolbar is now empty as the button helpers are deprecated.@jupyterlab/rendermime
:RenderMimeRegistry.IUrlResolverOptions
does not acceptsession
; you must set thepath
(accessible throughsession.path
).@jupyterlab/ui-components
:RankedMenu.menu : Menu
has been removed asRankedMenu
inherits fromMenu
.LabIconStyle.IProps
does not acceptkind
norjustify
. You should usestylesheet
orelementPosition
respectively.
Extension Development Changes#
The
externalExtensions
field in thedev_mode/package.json
file corresponding to the@jupyterlab/application-top
private
package has now been removed in4.0
. If you were using this field to develop source extensions against a development build of JupyterLab, you should instead switch to the federated extensions system (via the--extensions-in-dev-mode
flag) or to using the--splice-source
option. See Developing a prebuilt extension and Development workflow for source extensions for more information.The
webpack
dependency in@jupyterlab/builder
has been updated to5.72
(or newer). Base rules have been updated to use the Asset Modules instead of the previousfile-loader
,raw-loader
andurl-loader
. This might affect third-party extensions if they were relying on specific behaviors from these loaders.In JupyterLab 3.x, the CSS for a _disabled_ prebuilt extensions would still be loaded on the page. This is no longer the case in JupyterLab 4.0.
window.jupyterlab
is not exposed anymore when starting JupyterLab with the--expose-app-in-browser
flag. Usewindow.jupyterapp
instead.
JupyterLab 3.5 to 3.6#
AsyncIterable Support#
For the events service, we are using a JavaScript feature introduced in ES2018. If your code is
using TypeScript with ES2017 target (as JupyterLab 3.6), you will either need to update your
target to ES2018 or add "ES2018"
to the TypeScript lib option.
Note
JupyterLab 3.6.0 was released with an updated target “ES2018”. We strongly advise updating to 3.6.1, which reverts the target back to “ES2017”.
Jest configuration update#
If you are using jest to test your extension, some new ES6 packages dependencies are added to JupyterLab 3.6.
They need to be ignore when transforming the code with Jest. You will need to update the
transformIgnorePatterns
to match:
const esModules = [
'@jupyterlab/',
'@jupyter/ydoc',
'lib0',
'y\\-protocols',
'y\\-websocket',
'yjs'
].join('|');
// ...
transformIgnorePatterns: [`/node_modules/(?!${esModules}).+`]
For more information, have a look at Testing your extension.
Real-Time Collaboration#
In JupyterLab v3.6, it is necessary to install Jupyter Server v2.0 to use real-time collaboration. This requirement was introduced to take advantage of the new identity API in Jupyter Server v2.0.
On the other side, we also changed how JupyterLab loads documents (only in collaborative mode). Instead of using the content API, now the provider opens a WebSocket connection to the YDocWebSocketHandler, which is implemented in an external jupyter server extension.
In addition, the shared models’ package was moved to an external package called @jupyter/ydoc. All the extensions that depend on
@jupyterlab/shared-models
will need to update to depend in @jupyter/ydoc@~0.2.2
; the API should
be the same.
API Changes: To be able to fix RTC and make it stable. It was necessary to change the API and make a few breaking changes. These changes should not affect the vast majority of extensions. They will only affect a couple of extensions focused on RTC.
It was necessary to change the paradigm of how JupyterLab loads documents and replace the locking mechanism in the back-end. Instead of identifying the first client to open the document, it now centralizes the process by instantiating a YDoc client in the back-end. This client is the only one that loads the content of the document into memory and shares it with every other client connected.
The involved packages are:
@jupyterlab/docprovider
:The interface
IDocumentProvider
, now extends fromIDisposable
. Removed:acquireLock
,releaseLock
,setPath
,destroy
,requestInitialContent
andputInitializedState
. Added:ready
andisDisposed
.IDocumentProviderFactory.IOptions
is now templated withT extends ISharedDocument = ISharedDocument
. And theymodel
attribute has been renamedmodel
typedT
(relaxing typing fromYDocument
toISharedDocument
).WebSocketProviderWithLocks
has been renamed toWebSocketProvider
. It does not extendWebSocketProvider
fromy-websocket
anymore.WebSocketProvider.IOptions
has a new optional attribute,user
.
@jupyterlab/services
:The interface
IManager
has a new optional property,user
that implement User.IManager.The
ServiceManager
class implements the optional propertyuser
from theIManager
.
JupyterLab 3.0 to 3.1#
Jest configuration update#
If you are using jest to test your extension, some new ES6 packages dependencies are added to JupyterLab.
They need to be ignore when transforming the code with Jest. You will need to update the
transformIgnorePatterns
to match:
const esModules = [
'@jupyterlab/',
'lib0',
'y\\-protocols',
'y\\-websocket',
'yjs'
].join('|');
// ...
transformIgnorePatterns: [`/node_modules/(?!${esModules}).+`]
For more information, have a look at Testing your extension.
Note
Here is an example of pull request to update to JupyterLab 3.1 in @jupyterlab/git
extension:
jupyterlab/jupyterlab-git#files
JupyterLab 2.x to 3.x#
Here are some helpful tips for migrating an extension from JupyterLab 2.x to JupyterLab 3.x.
Upgrading library versions manually#
To update the extensions so it is compatible with the 3.0 release, update the compatibility
range of the @jupyterlab
dependencies in the package.json
. The diff should be similar to:
index 6f1562f..3fcdf37 100644
^^^ a/package.json
+++ b/package.json
"dependencies": {
- "@jupyterlab/application": "^2.0.0",
+ "@jupyterlab/application": "^3.0.0",
Upgrading library versions using the upgrade script#
JupyterLab 3.0 provides a script to upgrade an existing extension to use the new extension system and packaging.
First, make sure to update to JupyterLab 3.0 and install jupyter-packaging
and cookiecutter
. With pip
:
pip install jupyterlab -U
pip install jupyter-packaging cookiecutter
Or with conda
:
conda install -c conda-forge jupyterlab=3 jupyter-packaging cookiecutter
Then at the root folder of the extension, run:
python -m jupyterlab.upgrade_extension .
The upgrade script creates the necessary files for packaging the JupyterLab extension as a Python package, such as
setup.py
and pyproject.toml
.
The upgrade script also updates the dependencies in package.json
to the ^3.0.0
packages. Here is an example diff:
index 6f1562f..3fcdf37 100644
^^^ a/package.json
+++ b/package.json
@@ -29,9 +29,13 @@
"scripts": {
- "build": "tsc",
- "build:labextension": "npm run clean:labextension && mkdirp myextension/labextension && cd myextension/labextension && npm pack ../..",
- "clean": "rimraf lib tsconfig.tsbuildinfo",
+ "build": "jlpm run build:lib && jlpm run build:labextension:dev",
+ "build:prod": "jlpm run build:lib && jlpm run build:labextension",
+ "build:lib": "tsc",
+ "build:labextension": "jupyter labextension build .",
+ "build:labextension:dev": "jupyter labextension build --development True .",
+ "clean": "rimraf lib tsconfig.tsbuildinfo myextension/labextension",
+ "clean:all": "jlpm run clean:lib && jlpm run clean:labextension",
"clean:labextension": "rimraf myextension/labextension",
"eslint": "eslint . --ext .ts,.tsx --fix",
"eslint:check": "eslint . --ext .ts,.tsx",
@@ -59,12 +63,12 @@
]
},
"dependencies": {
- "@jupyterlab/application": "^2.0.0",
- "@jupyterlab/apputils": "^2.0.0",
- "@jupyterlab/observables": "^3.0.0",
+ "@jupyterlab/builder": "^3.0.0",
+ "@jupyterlab/application": "^3.0.0",
+ "@jupyterlab/apputils": "^3.0.0",
+ "@jupyterlab/observables": "^3.0.0",
"@lumino/algorithm": "^1.2.3",
"@lumino/commands": "^1.10.1",
"@lumino/disposable": "^1.3.5",
@@ -99,6 +103,13 @@
- "typescript": "~3.8.3"
+ "typescript": "~4.0.1"
},
"jupyterlab": {
- "extension": "lib/plugin"
+ "extension": "lib/plugin",
+ "outputDir": "myextension/labextension/"
}
}
On the diff above, we see that additional development scripts are also added, as they are used by the new extension system workflow.
The diff also shows the new @jupyterlab/builder
as a devDependency
.
@jupyterlab/builder
is a package required to build the extension as a federated (prebuilt) extension.
It hides away internal dependencies such as webpack
, and produces the assets that can then be distributed as part of a Python package.
Extension developers do not need to interact with @jupyterlab/builder
directly, but instead can use the
jupyter labextension build
command. This command is run automatically as part of the build
script
(jlpm run build
).
For more details about the new file structure and packaging of the extension, check out the extension tutorial: Extension Tutorial
Publishing the extension to PyPI and conda-forge#
Starting from JupyterLab 3.0, extensions can be distributed as a Python package.
The extension tutorial provides explanations to package the extension so it can be published on PyPI and conda forge: Publishing your extension.
Note
While publishing to PyPI is the new recommended way for distributing extensions to users,
it is still useful to continue publishing extensions to npm
as well,
so other developers can extend them in their own extensions.
JupyterLab 1.x to 2.x#
Here are some helpful tips for migrating an extension from JupyterLab 1.x to JupyterLab 2.x. We will look at two examples of extensions that cover most of the APIs that extension authors might be using:
@jupyterlab/debugger
migration pull request: jupyterlab/debugger#files@jupyterlab/shortcutui
migration pull request: jupyterlab/jupyterlab-shortcutui#files
Upgrading library versions#
The @phosphor/*
libraries that JupyterLab 1.x uses have been renamed to
@lumino/*
. Updating your package.json
is straightforward. The easiest
way to do this is to look in the
JupyterLab core packages code base
and to simply adopt the versions of the relevant libraries that are used
there.
Tip
In these examples, note that we are using the 2.0.0-beta.x
version of
many libraries. This was to test the extensions against the JupyterLab 2.0
beta release before the final version. For the final release, your
package.json
should depend on version ^2.0.0
of these packages.
Migrating from @phosphor
to @lumino
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
The foundational packages used by JupyterLab are now all prefixed with the NPM
namespace @lumino
instead of @phosphor
. The APIs for these packages
have not changed. The @phosphor
namespaced imports need to be updated to
the new @lumino
namespaced packages:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Warning
p-
prefixed CSS classes, data-p-
attributes and p-
DOM events
are deprecated. They will continue to work until the next major release of
Lumino.
.p-
CSS classes such as.p-Widget
should be updated to.lm-
, e.g..lm-Widget
data-p-
attributes such asdata-p-dragscroll
should be updated todata-lm-
, e.g.data-lm-dragscroll
p-
DOM events such asp-dragenter
should be updated tolm-
, e.g.lm-dragenter
Updating former @jupyterlab/coreutils
imports
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
JupyterLab 2.0 introduces several new packages with classes and tokens that
have been moved out of @jupyterlab/coreutils
into their own packages. These
exports have been moved.
Tip
It might be helpful to delete node_modules
and yarn.lock
when
updating these libraries.
Export |
Package |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Using Session
and SessionContext
to manage kernel sessions#
Note
For full API documentation and examples of how to use
@jupyterlab/services
,
consult the repository.
ConsolePanel
and NotebookPanel
now expose a
sessionContext: ISessionContext
attribute that allows for a uniform way to
interact with kernel sessions.
Any widget that matches the interface IDocumentWidget
has a
context: DocumentRegistry.IContext
attribute with a
sessionContext: ISessionContext
attribute.
For example, consider how the @jupyterlab/debugger
extension’s
DebuggerService
updated its isAvailable()
method.
Note
await kernel.ready
is no longer necessary before the kernel connection
kernel
can be used. Kernel messages will be buffered as needed while a
kernel connection is coming online, so you should be able to use a kernel
connection immediately. If you want to retrieve the kernel info (or if for
some other reason you want to wait until at least one message has returned
from a new kernel connection), you can do await kernel.info
.
Using the new icon system and LabIcon
#
Note
For full API documentation and examples of how to use
the new icon support based on LabIcon
from @jupyterlab/ui-components
,
consult the repository.