Notebook / Extensions / APIs === > #ipython, jupyter notebook, python notebook, jupyterlab, elyra ###### tags: `Jupyter` ###### tags: `Jupyter`, `JupyterLab`, `Notebook`, `Elyra`, `Extension` <br> [TOC] <br> <hr> <br> ## APIs 大全 ### jupyterlab - doc1 https://jupyterlab.readthedocs.io/en/stable/api/modules.html - doc2 (更詳細,有繼承資訊、實作介面) https://jupyterlab.github.io/jupyterlab/globals.html MainAreaWidget: [github](https://jupyterlab.github.io/jupyterlab/classes/_apputils_src_index_.mainareawidget.html) vs [readthedocs](https://jupyterlab.readthedocs.io/en/stable/api/modules/apputils.mainareawidget.html) - github https://github.com/jupyterlab/jupyterlab/tree/master/packages ### JupyterLab Services - [overview](https://github.com/jupyterlab/jupyterlab/blob/master/packages/services/README.md) - [doc](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml) ### lumino > Lumino is a set of JavaScript packages, written in TypeScript, that provide a rich toolkit of widgets, layouts, events, and data structures. These enable developers to construct extensible high-performance desktop-like web applications, such as JupyterLab. Lumino was formerly known as [PhosphorJS](https://phosphorjs.github.io/). > > Lumino 是一套使用 TypeScript 編寫而成的 JavaScript 套件,提供了豐富的 widge t(小工具)、layout (佈局)、event (事件) 和 data structure (資料結構) 工具箱。 這些使開發人員能夠建構可擴展的高效能類似桌面的 Web 應用應試,例如 JupyterLab。 Lumino 以前稱為 [PhosphorJS](https://phosphorjs.github.io/)。 > - doc https://jupyterlab.github.io/lumino/ - github https://github.com/jupyterlab/lumino/tree/main/packages <br> <hr> <br> ## `@jupyterlab/application` ### [`Class JupyterFrontEnd<T, U>`](https://jupyterlab.github.io/jupyterlab/classes/_application_src_index_.jupyterfrontend.html) > [github](https://github.com/jupyterlab/jupyterlab/blob/master/packages/application/src/frontend.ts) - [restored](https://jupyterlab.github.io/jupyterlab/classes/_application_src_index_.jupyterfrontend.html#restored) - 等待 app ready 的兩種作法 - 方法一(建議) ``` Promise.all([app.restored]).then(() => { console.log('ready1'); }); ``` - 方法二(不建議) ``` app.serviceManager.ready.then(() => { console.log('ready2'); }); ``` - ready2 會比 ready1 早執行 - 在此階段,shell 還未 ready,呼叫會失敗 ```typescript= import { JupyterFrontEnd, JupyterFrontEndPlugin } from '@jupyterlab/application'; import { MainAreaWidget } from '@jupyterlab/apputils'; import { Widget } from '@lumino/widgets'; /** * Initialization data for the my_test2 extension. */ const plugin: JupyterFrontEndPlugin<void> = { id: 'my_test2:plugin', autoStart: true, activate: (app: JupyterFrontEnd) => { console.log('my_test2 is activated!'); const content = new Widget(); const widget = new MainAreaWidget({content}); widget.title.label = 'MainArea'; app.serviceManager.ready.then(() => { console.log('[my_test2][1] is ready!'); console.log('[my_test2][1] >> widget.isAttached:', widget.isAttached); app.shell.add(widget, 'main'); // failed console.log('[my_test2][1] << widget.isAttached:', widget.isAttached); }); Promise.all([app.restored]) .then(() => { console.log('[my_test2][2] is ready!'); console.log('[my_test2][2] >> widget.isAttached:', widget.isAttached); app.shell.add(widget, 'main'); console.log('[my_test2][2] << widget.isAttached:', widget.isAttached); }); } }; export default plugin; ``` ![](https://i.imgur.com/zXYQ91S.png) - 底下有一些範例,不確定上面是否有誤用? - [signals](https://github.com/jupyterlab/extension-examples/blob/master/signals/src/index.ts#L64) - [Kernel Messaging](https://github.com/jupyterlab/extension-examples/blob/master/kernel-messaging/README.md) - [Kernel Output](https://github.com/jupyterlab/extension-examples/tree/master/kernel-output) <br> ## `@jupyterlab/apputils` > [[src]](https://github.com/jupyterlab/jupyterlab/blob/master/packages/apputils/src/) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/modules/apputils.html) ### showDialog > [[src]](https://github.com/jupyterlab/jupyterlab/blob/master/packages/apputils/src/dialog.tsx#L25) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/modules/apputils.html#showdialog) ### showErrorMessage > [[src]](https://github.com/jupyterlab/jupyterlab/blob/master/packages/apputils/src/dialog.tsx#L40) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/modules/apputils.html#showerrormessage) ```typescript= import { showErrorMessage } from '@jupyterlab/apputils'; showErrorMessage( 'Title: Error', 'Body: content' ); ``` ```typescript= import { Dialog, showErrorMessage } from '@jupyterlab/apputils'; showErrorMessage( 'Title: Error', 'Body: content', [Dialog.okButton({label: 'Dismiss'})] ); ``` ### MainAreaWidget > [[src]](https://github.com/jupyterlab/jupyterlab/blob/master/packages/apputils/src/mainareawidget.ts), [[doc1: readthedocs]](https://jupyterlab.readthedocs.io/en/stable/api/classes/apputils.mainareawidget-1.html), [[doc2: github]](https://jupyterlab.github.io/jupyterlab/classes/_apputils_src_index_.mainareawidget.html) - layout ![](https://i.imgur.com/7yZemAx.png) - id ```typescript import { UUID } from '@lumino/coreutils'; ``` ```typescript import { DOMUtils } from './domutils'; this.id = DOMUtils.createDomID(); ``` ### Toolbar > [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/classes/apputils.toolbar-1.html) <br> ## `@jupyterlab/coreutils` > [[src]](https://github.com/jupyterlab/jupyterlab/blob/master/packages/coreutils/src/) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/modules/coreutils.pageconfig.html) > > 資料來源: > 1. [jupyterlab-latex](https://github.com/jupyterlab/jupyterlab-latex/blob/master/src/index.ts) > - PathExt, URLExt ### PageConfig > [[src]](https://github.com/jupyterlab/jupyterlab/blob/master/packages/coreutils/src/pageconfig.ts) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/modules/coreutils.pageconfig.html) - ### [getOption](https://jupyterlab.readthedocs.io/en/stable/api/modules/coreutils.pageconfig.html#getoption) > Get global configuration data for the Jupyter application. - [How to access default paths from within the JupyterLab client (solved)](https://discourse.jupyter.org/t/how-to-access-default-paths-from-within-the-jupyterlab-client-solved/1509) - ### [setOption](https://jupyterlab.readthedocs.io/en/stable/api/modules/coreutils.pageconfig.html#setoption) > Set global configuration data for the Jupyter application. ### [PathExt](https://jupyterlab.readthedocs.io/en/stable/api/modules/coreutils.pathext.html) - ### [`dirname`](https://jupyterlab.readthedocs.io/en/stable/api/modules/coreutils.pathext.html#dirname), [`basename`](https://jupyterlab.readthedocs.io/en/stable/api/modules/coreutils.pathext.html#basename), [`extname`](https://jupyterlab.readthedocs.io/en/stable/api/modules/coreutils.pathext.html#extname) ```typescript= import { PathExt } from '@jupyterlab/coreutils'; const filename = '/xxx/yyy/zzz/README.md'; console.log("filename:", filename); console.log("dirname:", PathExt.dirname(filename)); console.log("basename:", PathExt.basename(filename)); console.log("extname:", PathExt.extname(filename)); ``` 執行結果: ```= filename: /xxx/yyy/zzz/README.md dirname: xxx/yyy/zzz basename: README.md extname: .md ``` - ### [`normalize`](https://jupyterlab.readthedocs.io/en/stable/api/modules/coreutils.pathext.html#normalize) ```typescript= import { PathExt } from '@jupyterlab/coreutils'; console.log("/xxx/README.md:", PathExt.normalize('./xxx/README.md')); console.log("/xxx///README.md:", PathExt.normalize('./xxx///README.md')); console.log("/xxx/yyy/../../zzz/README.md:", PathExt.normalize('/xxx/yyy/../../zzz/README.md')); ``` 執行結果: ```= /xxx/README.md: xxx/README.md /xxx///README.md: xxx/README.md /xxx/yyy/../zzz/README.md: zzz/README.md ``` <br> <hr> <br> ## `@jupyterlab/codeeditor` > Sources: > 1. [jupyterlab-latex](https://github.com/jupyterlab/jupyterlab-latex/blob/master/src/index.ts) - CodeEditor <br> <hr> <br> ## `@jupyterlab/docmanager-extension` [[src]](https://github.com/jupyterlab/jupyterlab/blob/master/packages/docmanager-extension) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/modules/docmanager_extension.html) <br> ### namespace CommandIDs > 並沒有 expose 出來 [[src]](https://github.com/jupyterlab/jupyterlab/blob/master/packages/docmanager-extension/src/index.tsx#L53) - deleteFile - newUntitled - open - rename - del - save - saveAll - saveAs <br> ### addCommands [[src]](https://github.com/jupyterlab/jupyterlab/blob/master/packages/docmanager-extension/src/index.tsx#L517) - ### [`commands.addCommand(CommandIDs.open, {...}`](https://github.com/jupyterlab/jupyterlab/blob/master/packages/docmanager-extension/src/index.tsx#L588) - ### [`commands.addCommand(CommandIDs.save, {...}`](https://github.com/jupyterlab/jupyterlab/blob/master/packages/docmanager-extension/src/index.tsx#L713) <br> <hr> <br> ## `@jupyterlab/mainmenu-extension` [[src]](https://github.com/jupyterlab/jupyterlab/tree/master/packages/mainmenu-extension/src) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/modules/mainmenu_extension.html) info: - [jtpio / jupyterlab-python-file](https://github.com/jtpio/jupyterlab-python-file) :+1: :+1: :+1: :100: <br> <hr> <br> ## `@jupyterlab/mainmenu` [[src]](https://github.com/jupyterlab/jupyterlab/tree/master/packages/mainmenu/src) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/modules/mainmenu.html) info: - [jtpio / jupyterlab-python-file](https://github.com/jtpio/jupyterlab-python-file) :+1: :+1: :+1: :100: ### debug menu ```typescript= activate: (app: JupyterFrontEnd, menu: IMainMenu | null) => { console.log('menu.fileMenu.menu:', menu); } ``` ![](https://i.imgur.com/GrfepCe.png) | menu | `_rank` | | -------------- | ---- | | `fileMenu` | 1 | | `editMenu` | 2 | | `viewMenu` | 3 | | `runMenu` | 4 | | `kernelMenu` | 5 | | `tabsMenu` | 500 | | `settingsMenu` | 999 | | `helpMenu` | 1000 | ### debug fileMenu ```typescript= activate: (app: JupyterFrontEnd, menu: IMainMenu | null) => { console.log('menu.fileMenu:', menu.fileMenu); } ``` ### 目標:停用 Log Out (command: `filemenu:logout`) ![](https://i.imgur.com/rQZU2j2.png) > **Q & A:** > - [Requesting help with how to remove menu items from the Jupyterlab Context menu](https://discourse.jupyter.org/t/requesting-help-with-how-to-remove-menu-items-from-the-jupyterlab-context-menu/3427) > ![](https://i.imgur.com/Lwxlfc7.png) > > - [Add hook to add/remove items from a filebrowser's contextMenu #3994](https://github.com/jupyterlab/jupyterlab/issues/3994) > ![](https://i.imgur.com/rak3rb8.png) > #暴力法 0. 該選項,定義在 [jupyterlab / packages / mainmenu-extension / src / index.ts#L438](https://github.com/jupyterlab/jupyterlab/blob/master/packages/mainmenu-extension/src/index.ts#L438) ![](https://i.imgur.com/jiIytcH.png) 1. 無法替換 `filemenu:logout` command,會有 error: ```typescript= commands.addCommand('filemenu:logout', { label: '[TJ] Log Out', caption: 'Log out of the Hub', isEnabled: () => false, execute: () => { console.log('logout is disabled'); } }); ``` > index.es6.js:289 Error: Command 'filemenu:logout' already registered. ![](https://i.imgur.com/cOdjlaz.png) 2. 從 commands 物件著手,嘗試存取: > Property '_commands' is ==**private**== and only accessible within class 'CommandRegistry'. ![](https://i.imgur.com/qyenpHf.png) 3. 從 [source code](https://github.com/jupyterlab/jupyterlab/blob/master/packages/mainmenu-extension/src/index.ts#L166) 著手 ==(有效 :+1:)== ```typescript==166 const quitButton = PageConfig.getOption('quitButton').toLowerCase(); menu.fileMenu.quitEntry = quitButton === 'true'; ``` - 添加程式碼 ``` menu.fileMenu.quitEntry = false; ``` - menu 選項變化 ![](https://i.imgur.com/znhw1dc.png =45%x) ![](https://i.imgur.com/F7EpiRq.png =45%x) - command pallete 選項 修改前: ![](https://i.imgur.com/v7uwSGa.png) 修改後: ![](https://i.imgur.com/vgNZY2d.png) 4. 透過 PageConfig.setOption() 變更選項值 ==(無效!!)== - 添加程式碼 ```typescript= import { PageConfig } from '@jupyterlab/coreutils'; ... Promise.all([app.restored]).then(() => { console.log(">> getOption('quitButton'):", PageConfig.getOption('quitButton')); PageConfig.setOption('quitButton', 'false'); console.log("<< getOption('quitButton'):", PageConfig.getOption('quitButton')); }); ``` - **無效原因:** 此時 menu.FileMenu 的屬性值已經被初始化 5. 直接從 `jupyter_lab_config.py` 修改 ==(有效 :+1:)== 1. 產生 config ``` $ jupyter-lab --generate-config Writing default config to: /home/tj/.jupyter/jupyter_lab_config.py ``` 2. 修改屬性 ![](https://i.imgur.com/d4WV9MR.png) 結果如下: ``` ## If True, display controls to shut down the Jupyter server, such as menu items # or buttons. # Default: True c.ServerApp.quit_button = False ``` - 參考資料 - [Lacking quit buttton after setting command line flag #8188](https://github.com/jupyterlab/jupyterlab/issues/8188) ![](https://i.imgur.com/aFi64j4.png) 6. 使用 js 模板,不使用 ts 模板,避開 ts 編譯器的檢查 ==(有效 :+1:)== ```javascript= Promise.all([app.researved]).then((_) => { // app 完成讀取後,然要等 mainmenu 載入完成 setTimeout(() => { cmd = app.commands._commands['filemenu:logout']; cmd.isEnabled = () => false; }, 2000); }); ``` ![](https://i.imgur.com/Ye5Z1S1.png) <br> ### 目標:移除 File menu ``` menu.fileMenu.dispose(); ``` <br> ### 目標:移除整個 menu ![](https://i.imgur.com/8mmVkdd.png) ``` $ jupyter labextension enable @jupyterlab/mainmenu-extension ``` <br> ### 目標:在 File > New 中加入選項 ![](https://i.imgur.com/V3j07Oa.png) ``` menu.fileMenu.newMenu.addGroup([{ command }], 0); menu.fileMenu.newMenu.addItem({ command }); ``` - 說明 - addGroup 後在 menu 前後加上分隔線 (separator) - 參考資料 - [jtpio / jupyterlab-python-file / src / index.ts](https://github.com/jtpio/jupyterlab-python-file/blob/main/src/index.ts#L88) <br> ### Class MainMenu [[src]](https://github.com/jupyterlab/jupyterlab/blob/master/packages/mainmenu/src/mainmenu.ts) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/classes/mainmenu.mainmenu-1.html) <br> <hr> <br> ## `@jupyterlab/services` [[src]](https://github.com/jupyterlab/jupyterlab/tree/master/packages/services) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/modules/services.html) info: - 如何讀取 local 端檔案 ### Namespace Contents [[src]](https://github.com/jupyterlab/jupyterlab/tree/master/packages/services/src/contents) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/modules/services.contents.html#contenttype) - ### SERVICE_DRIVE_URL #url, endpoint ``` /** * The url for the default drive service. */ const SERVICE_DRIVE_URL = 'api/contents'; ``` - ### Type ContentType [[src]](https://github.com/jupyterlab/jupyterlab/blob/master/packages/services/src/contents/index.ts#L118) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/modules/services.contents.html#contenttype) - ### Type FileFormat [[src]](https://github.com/jupyterlab/jupyterlab/blob/master/packages/services/src/contents/index.ts#L123) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/modules/services.contents.html#fileformat) - ### IManager.get > `get(path: string, options?: IFetchOptions): Promise<IModel>;` > Get a file or directory. [[src]](https://github.com/jupyterlab/jupyterlab/blob/master/packages/services/src/contents/index.ts#L696) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/interfaces/services.contents.imanager.html#get) #read, get, input, file - [用法1](https://github.com/jupyterlab/jupyterlab/blob/master/packages/docmanager-extension/src/index.tsx#L588) #docmanager-extension ```typescript= return docManager.services.contents .get(path, { content: false }) .then(() => docManager.openOrReveal(path, factory, kernel, options)); ``` - ### IManager.newuntitled > `IManager.newUntitled(options?: ICreateOptions): Promise<IModel>;` > Create a new untitled file or directory in the specified directory path. [[src]](https://github.com/jupyterlab/jupyterlab/blob/master/packages/services/src/contents/index.ts#L748) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/interfaces/services.contents.imanager.html#newuntitled) - [用法1](https://github.com/jupyterlab/jupyterlab/blob/master/packages/docmanager-extension/src/index.tsx#L588) #docmanager-extension ```typescript= return docManager.services.contents .newUntitled(options) .catch(error => showErrorMessage(errorTitle, error)); ``` - ### IManager.save > `IManager.save(path: string, options?: Partial<IModel>): Promise<IModel>;` > Save a file. [[src]](https://github.com/jupyterlab/jupyterlab/blob/master/packages/services/src/contents/index.ts#L810) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/interfaces/services.contents.imanager.html#save) #write, set, output, file - 範例 - [filebrowser/src/model.ts](https://github.com/jupyterlab/jupyterlab/blob/master/packages/filebrowser/src/model.ts#L459) ![](https://i.imgur.com/aMirjp5.png) - also - [docregistry/src/registry.ts#IContext.save()](https://github.com/jupyterlab/jupyterlab/blob/602b05399b0ca762613c8f560a49b15abdefee39/packages/docregistry/src/registry.ts#L966) - [docregistry/src/context.ts#save()](https://github.com/jupyterlab/jupyterlab/blob/602b05399b0ca762613c8f560a49b15abdefee39/packages/docregistry/src/context.ts#L298) - [docregistry/src/context.ts#_save()](https://github.com/jupyterlab/jupyterlab/blob/602b05399b0ca762613c8f560a49b15abdefee39/packages/docregistry/src/context.ts#L594) <br> ### Namespace ServerConnection [[src]](https://github.com/jupyterlab/jupyterlab/blob/master/packages/services/src/serverconnection.ts) [[doc]](https://jupyterlab.readthedocs.io/en/stable/api/modules/services.serverconnection.html) - ### [makeSettings](https://jupyterlab.readthedocs.io/en/stable/api/modules/services.serverconnection.html#makesettings) - [範例](https://github.com/jupyterlab/extension-examples/blob/master/server-extension/src/handler.ts#L17) - ### [makeRequest](https://jupyterlab.readthedocs.io/en/stable/api/modules/services.serverconnection.html#makerequest) <br> <hr> <br> ## [`@lumino/commands`](https://jupyterlab.github.io/lumino/commands/index.html) - [github](https://github.com/jupyterlab/lumino/blob/main/packages/commands/src/index.ts) - [JupyterLab doc](https://jupyterlab.readthedocs.io/en/stable/extension/extension_points.html#commands) ```typescript= const commandID = 'my-command'; let toggled = false; app.commands.addCommand(commandID, { label: 'My Cool Command', isEnabled: () => true, isVisible: () => true, isToggled: () => toggled, iconClass: 'some-css-icon-class', execute: () => { console.log(`Executed ${commandID}`); toggled = !toggled; }); ``` ### [`Class CommandRegistry`]() - [isEnabled](https://jupyterlab.github.io/lumino/commands/classes/commandregistry.html#isenabled) - [isToggled](https://jupyterlab.github.io/lumino/commands/classes/commandregistry.html#istoggled) - [isVisible](https://jupyterlab.github.io/lumino/commands/classes/commandregistry.html#isvisible) - [label](https://jupyterlab.github.io/lumino/commands/classes/commandregistry.html#label) <br> <hr> <br> ## JupyterLab Services > https://github.com/jupyterlab/jupyterlab/blob/master/packages/services/README.md ### REST API Docs > https://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml - ### 讓 yaml 跑在 local 端 ```yaml schemes: - "http" host: "localhost:8888" ``` - 但須額外添加 token (參數:`&token=xxx`) - token 來源:在執行 jupyter lab 時會顯示在 log 裡 - ### contents ![](https://i.imgur.com/vUFJrDx.png) - `/api/contents` <br> ### contents: get ```bash TOKEN=322a7f056033fb322ecdfc30b551bd306029eb37b669a1e0 curl "http://localhost:8888/api/contents/hello.py?type=file&format=text&content=1&token=$TOKEN" ``` - 要加雙引號才能正常執行 執行結果: ```json= { "name": "hello.py", "path": "hello.py", "last_modified": "2022-01-03T06:33:30.625767Z", "created": "2022-01-03T06:33:30.625767Z", "content": "print('hello!')", "format": "text", "mimetype": "text/x-python", "size": 15, "writable": true, "type": "file" } ``` <br> ### contents: save ```bash TOKEN=322a7f056033fb322ecdfc30b551bd306029eb37b669a1e0 curl -X 'PUT' \ "http://localhost:8888/api/contents/hello.py?token=${TOKEN}" \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "name": "hello.py", "path": "hello.py", "type": "file", "format": "text", "content": "print('\''hello!'\'')" }' ``` - `"http://localhost:8888/api/contents/hello.py?token=${TOKEN}"` - 要使用雙引號,才能引入 ${TOKEN} - 使用單引號會失敗 - path - api/contents/hello.py workspace:/hello.py - api/contents/sample/hello.py workspace:/sample/hello.py - 不清楚 body 中的 path 含意 執行結果: ```json= { "name": "hello.py", "path": "hello.py", "last_modified": "2022-01-03T06:40:33.632436Z", "created": "2022-01-03T06:40:33.632436Z", "content": null, "format": null, "mimetype": "text/x-python", "size": 15, "writable": true, "type": "file" } ``` <br> <hr> <br> ## Tornado ### Application.add_handlers(handlers: List[Union[Rule, Tuple]]) > [[src]](https://www.tornadoweb.org/en/stable/_modules/tornado/web.html#Application.add_handlers) [[doc]](https://www.tornadoweb.org/en/stable/web.html#tornado.web.Application.add_handlers) - [tornado.web.Application類配置及使用](https://www.codeprj.com/zh/blog/58e01a1.html) <br> <hr> <br> ## 參考資料 ### @jupyterlab/docmanager - [How to use @jupyterlab/docmanager - 10 common examples](https://snyk.io/advisor/npm-package/@jupyterlab/docmanager/example)