Repository: deshaw/jupyterlab-execute-time (language: python)

Issue:
JupyterLab settings missing
In JL v4.1.8 I'm not seeing any settings for this [`jupyterlab-execute-time`](https://github.com/deshaw/jupyterlab-execute-time) extension?


Discussion / hints:
If you close the settings and open them again, does it show up?
If so then this is a duplicate of https://github.com/deshaw/jupyterlab-execute-time/issues/98 - there is an upstream bug that settings for plugins which load later than others do not show up if the settings panel is open on startup (https://github.com/jupyterlab/jupyterlab/issues/15871). It is quite annoying because it also affects the settings built-in plugins like Inline Completer.
Nope... opening and closing the settings editor had no effect. I guessed at the path name for the user settings file too to see if I could manually override some settings but either I guessed the path wrong, or that didn't work either...
> opening and closing the settings editor had no effect

Indeed, opening and closing does not help, unless you also open a notebook in the meantime. I can reproduce this reliably.

![repro](https://github.com/deshaw/jupyterlab-execute-time/assets/5832902/d9d83928-e875-4112-a294-99a5174fe603)

The problem here is that the settings UI only adds plugins to UI when the settings are loaded by the extension. ` jupyterlab-execute-time` only loads the settings after opening a notebook.

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 42d11b7..d5442c6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,10 @@
 
 - Add an option to show the cell outputs per second [#116](https://github.com/deshaw/jupyterlab-execute-time/pull/116)
 
+### Fixed
+
+- Fix extension not showing up in the Settings Editor [#120](https://github.com/deshaw/jupyterlab-execute-time/pull/120)
+
 ## [3.1.2](https://github.com/deshaw/jupyterlab-execute-time/compare/v3.1.0...v3.1.2) (2024-02-14)
 
 ### Fixed
diff --git a/src/ExecuteTimeWidget.ts b/src/ExecuteTimeWidget.ts
index 439bc28..b8c40e5 100644
--- a/src/ExecuteTimeWidget.ts
+++ b/src/ExecuteTimeWidget.ts
@@ -39,41 +39,16 @@ export default class ExecuteTimeWidget extends Widget {
   constructor(
     panel: NotebookPanel,
     tracker: INotebookTracker,
-    settingRegistry: ISettingRegistry
+    settings: ISettingRegistry.ISettings
   ) {
     super();
     this._panel = panel;
     this._tracker = tracker;
-    this._settingRegistry = settingRegistry;
 
     this.updateConnectedCell = this.updateConnectedCell.bind(this);
-    settingRegistry.load(`${PLUGIN_NAME}:settings`).then(
-      (settings: ISettingRegistry.ISettings) => {
-        this._updateSettings(settings);
-        settings.changed.connect(this._updateSettings.bind(this));
-
-        // If the plugin is enabled, force recording of timing
-        // We only do this once (not on every settings update) in case the user tries to turn it off
-        if (settings.get('enabled').composite) {
-          this._settingRegistry
-            .load('@jupyterlab/notebook-extension:tracker')
-            .then(
-              (nbSettings: ISettingRegistry.ISettings) =>
-                nbSettings.set('recordTiming', true),
-              (err: Error) => {
-                console.error(
-                  `jupyterlab-execute-time: Could not force metadata recording: ${err}`
-                );
-              }
-            );
-        }
-      },
-      (err: Error) => {
-        console.error(
-          `jupyterlab-execute-time: Could not load settings, so did not active ${PLUGIN_NAME}: ${err}`
-        );
-      }
-    );
+
+    this._updateSettings(settings);
+    settings.changed.connect(this._updateSettings.bind(this));
   }
 
   /**
@@ -517,7 +492,6 @@ export default class ExecuteTimeWidget extends Widget {
   } = {};
   private _tracker: INotebookTracker;
   private _panel: NotebookPanel;
-  private _settingRegistry: ISettingRegistry;
   private _settings: IExecuteTimeSettings = {
     enabled: false,
     highlight: true,
diff --git a/src/index.ts b/src/index.ts
index 92d5028..d5ac714 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -12,8 +12,8 @@ import { DocumentRegistry } from '@jupyterlab/docregistry';
 import ExecuteTimeWidget, { PLUGIN_NAME } from './ExecuteTimeWidget';
 
 class ExecuteTimeWidgetExtension implements DocumentRegistry.WidgetExtension {
-  constructor(tracker: INotebookTracker, settingRegistry: ISettingRegistry) {
-    this._settingRegistry = settingRegistry;
+  constructor(tracker: INotebookTracker, settings: ISettingRegistry.ISettings) {
+    this._settings = settings;
     this._tracker = tracker;
   }
 
@@ -22,10 +22,10 @@ class ExecuteTimeWidgetExtension implements DocumentRegistry.WidgetExtension {
     panel: NotebookPanel,
     context: DocumentRegistry.IContext<INotebookModel>
   ) {
-    return new ExecuteTimeWidget(panel, this._tracker, this._settingRegistry);
+    return new ExecuteTimeWidget(panel, this._tracker, this._settings);
   }
 
-  private _settingRegistry: ISettingRegistry;
+  private _settings: ISettingRegistry.ISettings;
   private _tracker: INotebookTracker;
 }
 
@@ -36,14 +36,38 @@ const extension: JupyterFrontEndPlugin<void> = {
   id: PLUGIN_NAME,
   autoStart: true,
   requires: [INotebookTracker, ISettingRegistry],
-  activate: (
+  activate: async (
     app: JupyterFrontEnd,
     tracker: INotebookTracker,
     settingRegistry: ISettingRegistry
   ) => {
+    let settings: ISettingRegistry.ISettings;
+    try {
+      settings = await settingRegistry.load(`${PLUGIN_NAME}:settings`);
+    } catch (err: unknown) {
+      console.error(
+        `jupyterlab-execute-time: Could not load settings, so did not active ${PLUGIN_NAME}: ${err}`
+      );
+      return;
+    }
+
+    // If the plugin is enabled, force recording of timing
+    // We only do this once (not on every settings update) in case the user tries to turn it off
+    if (settings.get('enabled').composite) {
+      settingRegistry.load('@jupyterlab/notebook-extension:tracker').then(
+        (nbSettings: ISettingRegistry.ISettings) =>
+          nbSettings.set('recordTiming', true),
+        (err: Error) => {
+          console.error(
+            `jupyterlab-execute-time: Could not force metadata recording: ${err}`
+          );
+        }
+      );
+    }
+
     app.docRegistry.addWidgetExtension(
       'Notebook',
-      new ExecuteTimeWidgetExtension(tracker, settingRegistry)
+      new ExecuteTimeWidgetExtension(tracker, settings)
     );
 
     // eslint-disable-next-line no-console


Test patch:
diff --git a/ui-tests/tests/settings_editor.spec.ts b/ui-tests/tests/settings_editor.spec.ts
new file mode 100644
index 0000000..10e27b1
--- /dev/null
+++ b/ui-tests/tests/settings_editor.spec.ts
@@ -0,0 +1,15 @@
+import { expect, test } from '@jupyterlab/galata';
+
+test.describe('Settings Editor', () => {
+  test('Execute Time show up in the Settings Editor', async ({ page }) => {
+    await page.evaluate(async () => {
+      await window.jupyterapp.commands.execute('settingeditor:open');
+    });
+    const plugin = page.locator(
+      '.jp-PluginList .jp-PluginList-entry >> text="Execute Time"'
+    );
+
+    await plugin.waitFor();
+    expect(plugin).toHaveCount(1);
+  });
+});