Changes to jupyterlab source code are not getting reflected

I need to make some javascript changes to jupyterlab source code. I am modifying notebook-extension and couple other javascript packages. I am able to see the code changes while running jupyterlab with dev-mode but these changes are not reflected when running without dev-mode. How can I build jupyterlab with my code changes so I can use it in production?

I am using following commands to build as mentioned in the docs.

git clone https://github.com/jupyterlab/jupyterlab.git
cd jupyterlab
pip install -e .
jlpm
jlpm run build:packages

You’ll need to emulate enough of the machinery to generate your own installable package, as your custom packages would be clobbered by the “real” ones. See this thread for some more discussion.

Another, far lighter-weight approach, would be to fork/extend the extensions in question, and build renamed packages which replace the core ones in the dependency injection stage at startup by specifying the package.json#/jupyterlab/disabledExtensions keyword. This will allow you to install the upstream, and maintain (hopefully) a much smaller set of changes/workflows.

thanks @bollwyvl for the reply. I am pretty new to jupyerlab so please pardon my ignorance. Please correct if my understanding is wrong. Here are the steps I would follow to build JL with my custom JS patch.

  1. disable notebook-extension
  2. copy notebook-extension code and rename it to my-custom-extension, apply required code changes.
  3. build the code using usual process

Is that what I should do ?

If you’re dead-set on building from source, the initially linked-discussion is the thing to follow.

In the patching approach, the idea is not to build a new jupyterlab 3.1.9.post1235 package pip package, but rather a @my-company/my-custom-notebook npm-compatible package, which implements the same API as @jupyterlab/notebook, and then a pip package, e.g. jupyterlab-my-custom-notebook

I’d recommend following the whole cookiecutter, getting out a “dumb” hello world extension as a pip installable package, then, as described in the link to the docs/schema, you’ll see where you can add disabledExtensions to your package.json.

Eventually, then, you’d do something like pip install jupyterlab jupyterlab-my-custom-notebook, and would be able to upgrade your jupyterlab independently of your jupyterlab… otherwise, you run the risk of users upgrading your jupyterlab and losing your changes.

Hi @sanket-qp, were you able to follow this approach?

I am trying to create my own modified version of @jupyterlab/notebook

I am playing with a UI element (in my case it’s a new cell button defined in packages/notebook/src/notebookfooter.ts). I am able to build a dev version of JupyterLab with my changes, but now I would like to distribute it, so I users don’t have to install a fork of jupyterlab and I don’t have to maintain such a fork as @bollwyvl said.

This is what I’m doing:

  1. Copy @jupyterlab/notebook source to a new project folder
  2. Change name in package.json from @jupyterlab/notebook to @my-company/my-custom-notebook.
  3. Apply my changes to the core library and build
jlpm install
jlpm run build

At this point I am getting tons of errors.

  1. tsconfig is interconnected between extensions. When I’m trying to remove extends and references from my tsconfig, I am starting to get hunderds of errors, many of which of a pattern Cannot find module '@jupyterlab/xyz' or its corresponding type declarations, i.e.
src/truststatus.tsx:6:22 - error TS2307: Cannot find module '@jupyterlab/cells' or its corresponding type declarations.

6 import { Cell } from '@jupyterlab/cells';

I am able to reduce the number of errors using this tsconfig file

{
  "$schema": "http://json.schemastore.org/tsconfig",
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "composite": true,
    "declaration": true,
    "esModuleInterop": true,
    "incremental": true,
    "jsx": "react",
    "lib": [
      "DOM",
      "DOM.Iterable",
      "ES2018",
      "ES2020.BigInt",
      "ES2020.Intl",
      "ES2020.String"
    ],
    "module": "esnext",
    "moduleResolution": "node",
    "outDir": "lib",
    "rootDir": "src",
    "target": "ES2018",
    "sourceMap": true,
    "strict": true,
    "noImplicitAny": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "strictPropertyInitialization": false,
    "useUnknownInCatchVariables": false
  },
  "include": ["src/*", "src/default.json"],
  "exclude": ["node_modules"]
}
Remaining errors
src/widget.ts:40:31 - error TS2307: Cannot find module '../../cells/src/model' or its corresponding type declarations.

40 import { CodeCellModel } from '../../cells/src/model';
                                 ~~~~~~~~~~~~~~~~~~~~~~~

node_modules/@jupyterlab/services/src/kernel/comm.ts:56:5 - error TS2322: Type '(msg: ICommCloseMsg<"iopub">) => void | PromiseLike<void>' is not assignable to type '(msg: ICommCloseMsg<"iopub" | "shell">) => void | PromiseLike<void>'.
  Types of parameters 'msg' and 'msg' are incompatible.
    Type 'ICommCloseMsg<"iopub" | "shell">' is not assignable to type 'ICommCloseMsg<"iopub">'.
      Type '"iopub" | "shell"' is not assignable to type '"iopub"'.
        Type '"shell"' is not assignable to type '"iopub"'.

56     return this._onClose;
       ~~~~~~

node_modules/@jupyterlab/services/src/kernel/default.ts:290:7 - error TS2345: Argument of type 'typeof KernelShellFutureHandler' is not assignable to parameter of type 'new (...params: any[]) => KernelFutureHandler<IShellControlMessage, IShellControlMessage>'.
  Types of construct signatures are incompatible.
    Type 'new <REQUEST extends IShellMessage<ShellMessageType> = IShellMessage<ShellMessageType>, REPLY extends IShellMessage<ShellMessageType> = IShellMessage<...>>(cb: () => void, msg: REQUEST, expectReply: boolean, disposeOnDone: boolean, kernel: IKernelConnection) => KernelShellFutureHandler<...>' is not assignable to type 'new (...params: any[]) => KernelFutureHandler<IShellControlMessage, IShellControlMessage>'.
      Construct signature return types 'KernelShellFutureHandler<any, IShellMessage<ShellMessageType>>' and 'KernelFutureHandler<IShellControlMessage, IShellControlMessage>' are incompatible.
        The types of 'onReply' are incompatible between these types.
          Type '(msg: IShellMessage<ShellMessageType>) => void | PromiseLike<void>' is not assignable to type '(msg: IShellControlMessage) => void | PromiseLike<void>'.
            Types of parameters 'msg' and 'msg' are incompatible.
              Type 'IShellControlMessage' is not assignable to type 'IShellMessage<ShellMessageType>'.
                Type 'IControlMessage<ControlMessageType>' is not assignable to type 'IShellMessage<ShellMessageType>'.
                  Types of property 'channel' are incompatible.
                    Type '"control"' is not assignable to type '"shell"'.

290       KernelShellFutureHandler,
          ~~~~~~~~~~~~~~~~~~~~~~~~

node_modules/@jupyterlab/services/src/kernel/default.ts:321:7 - error TS2345: Argument of type 'typeof KernelControlFutureHandler' is not assignable to parameter of type 'new (...params: any[]) => KernelFutureHandler<IShellControlMessage, IShellControlMessage>'.
  Types of construct signatures are incompatible.
    Type 'new <REQUEST extends IControlMessage<ControlMessageType> = IControlMessage<ControlMessageType>, REPLY extends IControlMessage<ControlMessageType> = IControlMessage<...>>(cb: () => void, msg: REQUEST, expectReply: boolean, disposeOnDone: boolean, kernel: IKernelConnection) => KernelControlFutureHandler<...>' is not assignable to type 'new (...params: any[]) => KernelFutureHandler<IShellControlMessage, IShellControlMessage>'.
      Construct signature return types 'KernelControlFutureHandler<any, IControlMessage<ControlMessageType>>' and 'KernelFutureHandler<IShellControlMessage, IShellControlMessage>' are incompatible.
        The types of 'onReply' are incompatible between these types.
          Type '(msg: IControlMessage<ControlMessageType>) => void | PromiseLike<void>' is not assignable to type '(msg: IShellControlMessage) => void | PromiseLike<void>'.
            Types of parameters 'msg' and 'msg' are incompatible.
              Type 'IShellControlMessage' is not assignable to type 'IControlMessage<ControlMessageType>'.
                Type 'IShellMessage<ShellMessageType>' is not assignable to type 'IControlMessage<ControlMessageType>'.
                  Types of property 'channel' are incompatible.
                    Type '"shell"' is not assignable to type '"control"'.

321       KernelControlFutureHandler,
          ~~~~~~~~~~~~~~~~~~~~~~~~~~

node_modules/@jupyterlab/services/src/kernel/default.ts:376:42 - error TS2345: Argument of type 'KernelFutureHandler<REQUEST, REPLY>' is not assignable to parameter of type 'KernelFutureHandler<IShellControlMessage, IShellControlMessage>'.
  Types of property 'onReply' are incompatible.
    Type '(msg: REPLY) => void | PromiseLike<void>' is not assignable to type '(msg: IShellControlMessage) => void | PromiseLike<void>'.
      Types of parameters 'msg' and 'msg' are incompatible.
        Type 'IShellControlMessage' is not assignable to type 'REPLY'.
          'IShellControlMessage' is assignable to the constraint of type 'REPLY', but 'REPLY' could be instantiated with a different subtype of constraint 'IShellControlMessage'.
            Type 'IShellMessage<ShellMessageType>' is not assignable to type 'REPLY'.
              'IShellMessage<ShellMessageType>' is assignable to the constraint of type 'REPLY', but 'REPLY' could be instantiated with a different subtype of constraint 'IShellControlMessage'.

376     this._futures.set(msg.header.msg_id, future);
                                             ~~~~~~

node_modules/@jupyterlab/services/src/kernel/default.ts:377:5 - error TS2322: Type 'KernelFutureHandler<REQUEST, REPLY>' is not assignable to type 'IFuture<IShellControlMessage, IShellControlMessage>'.
  Types of property 'onReply' are incompatible.
    Type '(msg: REPLY) => void | PromiseLike<void>' is not assignable to type '(msg: IShellControlMessage) => void | PromiseLike<void>'.
      Types of parameters 'msg' and 'msg' are incompatible.
        Type 'IShellControlMessage' is not assignable to type 'REPLY'.
          'IShellControlMessage' is assignable to the constraint of type 'REPLY', but 'REPLY' could be instantiated with a different subtype of constraint 'IShellControlMessage'.
            Type 'IShellMessage<ShellMessageType>' is not assignable to type 'REPLY'.
              'IShellMessage<ShellMessageType>' is assignable to the constraint of type 'REPLY', but 'REPLY' could be instantiated with a different subtype of constraint 'IShellControlMessage'.

377     return future;
        ~~~~~~

node_modules/@jupyterlab/services/src/terminal/default.ts:278:5 - error TS2322: Type '(event: CloseEvent) => void' is not assignable to type '(this: WebSocket, ev: Event) => any'.
  Types of parameters 'event' and 'ev' are incompatible.
    Type 'Event' is missing the following properties from type 'CloseEvent': code, reason, wasClean

278     this._ws.onerror = this._onWSClose;
        ~~~~~~~~~~~~~~~~

src/notebooklspadapter.ts:221:7 - error TS2345: Argument of type '(_session: SessionContext, change: IKernelChangedArgs) => Promise<void>' is not assignable to parameter of type 'Slot<ISessionContext, IChangedArgs<IKernelConnection | null, IKernelConnection | null, "kernel">>'.
  Types of parameters '_session' and 'sender' are incompatible.
    Type 'ISessionContext' is missing the following properties from type 'SessionContext': noKernelName, _initialize, _shutdownSession, _startIfNecessary, and 43 more.

221       this.onKernelChanged,
          ~~~~~~~~~~~~~~~~~~~~

src/notebooklspadapter.ts:362:7 - error TS2345: Argument of type '(_session: SessionContext, change: IKernelChangedArgs) => Promise<void>' is not assignable to parameter of type 'Slot<ISessionContext, IChangedArgs<IKernelConnection | null, IKernelConnection | null, "kernel">>'.

362       this.onKernelChanged,
          ~~~~~~~~~~~~~~~~~~~~

src/toc.ts:100:7 - error TS2345: Argument of type '(notebook: Notebook, cell: Cell<ICellModel>) => void' is not assignable to parameter of type 'Slot<Notebook, Cell<ICellModel> | null>'.
  Types of parameters 'cell' and 'args' are incompatible.
    Type 'Cell<ICellModel> | null' is not assignable to type 'Cell<ICellModel>'.
      Type 'null' is not assignable to type 'Cell<ICellModel>'.

100       this.onActiveCellChanged,
          ~~~~~~~~~~~~~~~~~~~~~~~~

src/toc.ts:104:38 - error TS2345: Argument of type '(_: unknown, args: { notebook: Notebook; cell: Cell<ICellModel>; success: boolean; error: KernelError | null; }) => void' is not assignable to parameter of type 'Slot<any, { notebook: Notebook; cell: Cell<ICellModel>; success: boolean; error?: KernelError | null | undefined; }>'.
  Types of parameters 'args' and 'args' are incompatible.
    Type '{ notebook: Notebook; cell: Cell<ICellModel>; success: boolean; error?: KernelError | null | undefined; }' is not assignable to type '{ notebook: Notebook; cell: Cell<ICellModel>; success: boolean; error: KernelError | null; }'.
      Types of property 'error' are incompatible.
        Type 'KernelError | null | undefined' is not assignable to type 'KernelError | null'.
          Type 'undefined' is not assignable to type 'KernelError | null'.

104     NotebookActions.executed.connect(this.onExecuted, this);
                                         ~~~~~~~~~~~~~~~

src/toc.ts:181:7 - error TS2345: Argument of type '(notebook: Notebook, cell: Cell<ICellModel>) => void' is not assignable to parameter of type 'Slot<Notebook, Cell<ICellModel> | null>'.

181       this.onActiveCellChanged,
          ~~~~~~~~~~~~~~~~~~~~~~~~

src/toc.ts:188:41 - error TS2345: Argument of type '(_: unknown, args: { notebook: Notebook; cell: Cell<ICellModel>; success: boolean; error: KernelError | null; }) => void' is not assignable to parameter of type 'Slot<any, { notebook: Notebook; cell: Cell<ICellModel>; success: boolean; error?: KernelError | null | undefined; }>'.

188     NotebookActions.executed.disconnect(this.onExecuted, this);
                                            ~~~~~~~~~~~~~~~

src/toc.ts:766:42 - error TS2345: Argument of type '(model: NotebookToCModel, heading: INotebookHeading | null) => void' is not assignable to parameter of type 'Slot<IModel<INotebookHeading>, INotebookHeading | null>'.
  Types of parameters 'model' and 'sender' are incompatible.
    Type 'IModel<INotebookHeading>' is missing the following properties from type 'NotebookToCModel': parser, sanitizer, isAlwaysActive, getCellHeadings, and 27 more.

766       model.activeHeadingChanged.connect(onActiveHeadingChanged);
                                             ~~~~~~~~~~~~~~~~~~~~~~

src/toc.ts:767:37 - error TS2345: Argument of type '(model: NotebookToCModel) => void' is not assignable to parameter of type 'Slot<IModel<INotebookHeading>, void>'.
  Types of parameters 'model' and 'sender' are incompatible.
    Type 'IModel<INotebookHeading>' is not assignable to type 'NotebookToCModel'.

767       model.headingsChanged.connect(onHeadingsChanged);
                                        ~~~~~~~~~~~~~~~~~

src/toc.ts:768:37 - error TS2345: Argument of type '(_: NotebookToCModel, heading: INotebookHeading | null) => void' is not assignable to parameter of type 'Slot<IModel<INotebookHeading>, INotebookHeading | null>'.
  Types of parameters '_' and 'sender' are incompatible.
    Type 'IModel<INotebookHeading>' is not assignable to type 'NotebookToCModel'.

768       model.collapseChanged.connect(onHeadingCollapsed);
                                        ~~~~~~~~~~~~~~~~~~

src/toc.ts:769:44 - error TS2345: Argument of type '(_: unknown, cell: MarkdownCell) => void' is not assignable to parameter of type 'Slot<Notebook, Cell<ICellModel>>'.
  Types of parameters 'cell' and 'args' are incompatible.
    Type 'Cell<ICellModel>' is missing the following properties from type 'MarkdownCell': headingInfo, headingCollapsed, numberChildNodes, headingCollapsedChanged, and 31 more.

769       widget.content.cellCollapsed.connect(onCellCollapsed);
                                               ~~~~~~~~~~~~~~~

src/toc.ts:772:47 - error TS2345: Argument of type '(model: NotebookToCModel, heading: INotebookHeading | null) => void' is not assignable to parameter of type 'Slot<IModel<INotebookHeading>, INotebookHeading | null>'.

772         model.activeHeadingChanged.disconnect(onActiveHeadingChanged);
                                                  ~~~~~~~~~~~~~~~~~~~~~~

src/toc.ts:773:42 - error TS2345: Argument of type '(model: NotebookToCModel) => void' is not assignable to parameter of type 'Slot<IModel<INotebookHeading>, void>'.

773         model.headingsChanged.disconnect(onHeadingsChanged);
                                             ~~~~~~~~~~~~~~~~~

src/toc.ts:774:42 - error TS2345: Argument of type '(_: NotebookToCModel, heading: INotebookHeading | null) => void' is not assignable to parameter of type 'Slot<IModel<INotebookHeading>, INotebookHeading | null>'.

774         model.collapseChanged.disconnect(onHeadingCollapsed);
                                             ~~~~~~~~~~~~~~~~~~

src/toc.ts:775:49 - error TS2345: Argument of type '(_: unknown, cell: MarkdownCell) => void' is not assignable to parameter of type 'Slot<Notebook, Cell<ICellModel>>'.

775         widget.content.cellCollapsed.disconnect(onCellCollapsed);
                                                    ~~~~~~~~~~~~~~~

src/toc.ts:782:5 - error TS2322: Type 'NotebookToCModel' is not assignable to type 'TableOfContentsModel<IHeading, NotebookPanel>'.
  Types of property 'activeHeadingChanged' are incompatible.
    Type 'ISignal<IModel<INotebookHeading>, INotebookHeading | null>' is not assignable to type 'ISignal<IModel<IHeading>, IHeading | null>'.
      Type 'IModel<INotebookHeading>' is not assignable to type 'IModel<IHeading>'.
        Types of property 'toggleCollapse' are incompatible.
          Type '(options: { heading?: INotebookHeading | undefined; collapsed?: boolean | undefined; }) => void' is not assignable to type '(options: { heading?: IHeading | undefined; collapsed?: boolean | undefined; }) => void'.
            Types of parameters 'options' and 'options' are incompatible.
              Type '{ heading?: IHeading | undefined; collapsed?: boolean | undefined; }' is not assignable to type '{ heading?: INotebookHeading | undefined; collapsed?: boolean | undefined; }'.
                Types of property 'heading' are incompatible.
                  Type 'IHeading | undefined' is not assignable to type 'INotebookHeading | undefined'.
                    Type 'IHeading' is not assignable to type 'INotebookHeading'.

782     return model;
        ~~~~~~

src/tracker.ts:54:45 - error TS2345: Argument of type '(sender: Notebook, cell: Cell<ICellModel>) => void' is not assignable to parameter of type 'Slot<Notebook, Cell<ICellModel> | null>'.
  Types of parameters 'cell' and 'args' are incompatible.
    Type 'Cell<ICellModel> | null' is not assignable to type 'Cell<ICellModel>'.
      Type 'null' is not assignable to type 'Cell<ICellModel>'.

54     panel.content.activeCellChanged.connect(this._onActiveCellChanged, this);
                                               ~~~~~~~~~~~~~~~~~~~~~~~~~


Found 23 errors.

but I am stuck afterwards. Not really sure what needs to be changed, so I can compile my modified library.

I document my efforts here: GitHub - orbrx/my-custom-notebook