Skip to content

Commit

Permalink
Update the method for determining kernel language (#354)
Browse files Browse the repository at this point in the history
* Update the method for determining kernel language

The previous algorithm for `getNotebookType()` was based on getting the
kernel spec out of the current notebook. This is a problem when format
is triggered by, for example, `jupyterlab-autosave-on-focus-change`,
immediately after notebook creation. In that case, the language is
determined to be `null` and errors arise.

Now the `onSave()` handler waits for the `sessionContext` to be ready,
then `getNotebookType()` gets the same kernel spec info from the session
rather than the loaded notebook.

* Make metadata access safer at runtime

The `!` operator is a type assertion that the attribute is not null, but
does nothing at runtime to ensure this is the case. I haven't yet found
reproduction steps for this failure, but I encountered a case where
accessing `model!.sharedModel` threw an error. This commit adds optional
chaining operators, which do provide protection at runtime.

* Fall back to session check if metadata is missing

`getNotebookType()` has two ways to determine the language. If the
metadata check fails, it falls through to the current session check.
Previously, if metadata was `null`, the method would return early.
  • Loading branch information
shreve authored Aug 14, 2024
1 parent 9a503ef commit 1323459
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 20 deletions.
50 changes: 30 additions & 20 deletions src/formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,34 +92,44 @@ export class JupyterlabNotebookCodeFormatter extends JupyterlabCodeFormatter {
return codeCells;
}

private getNotebookType() {
private getNotebookType(): string | null {
// If there is no current notebook, there is nothing to do
if (!this.notebookTracker.currentWidget) {
return null;
}

// first, check the notebook's metadata for language info
const metadata =
this.notebookTracker.currentWidget.content.model!.sharedModel.metadata;

if (!metadata) {
return null;
}
this.notebookTracker.currentWidget.content.model?.sharedModel?.metadata;

if (metadata) {
// prefer kernelspec language
if (
metadata.kernelspec &&
metadata.kernelspec.language &&
typeof metadata.kernelspec.language === 'string'
) {
return metadata.kernelspec.language.toLowerCase();
}

// prefer kernelspec language
if (
metadata.kernelspec &&
metadata.kernelspec.language &&
typeof metadata.kernelspec.language === 'string'
) {
return metadata.kernelspec.language.toLowerCase();
// otherwise, check language info code mirror mode
if (metadata.language_info && metadata.language_info.codemirror_mode) {
const mode = metadata.language_info.codemirror_mode;
if (typeof mode === 'string') {
return mode.toLowerCase();
} else if (typeof mode.name === 'string') {
return mode.name.toLowerCase();
}
}
}

// otherwise, check language info code mirror mode
if (metadata.language_info && metadata.language_info.codemirror_mode) {
const mode = metadata.language_info.codemirror_mode;
if (typeof mode === 'string') {
return mode.toLowerCase();
} else if (typeof mode.name === 'string') {
return mode.name.toLowerCase();
// in the absence of metadata, look in the current session's kernel spec
const sessionContext = this.notebookTracker.currentWidget.sessionContext;
const kernelName = sessionContext?.session?.kernel?.name;
if (kernelName) {
const specs = sessionContext.specsManager.specs?.kernelspecs;
if (specs && kernelName in specs) {
return specs[kernelName]!.language;
}
}

Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class JupyterLabCodeFormatter
state: DocumentRegistry.SaveState
) {
if (state === 'started' && this.config.formatOnSave) {
await context.sessionContext.ready;
await this.notebookCodeFormatter.formatAllCodeCells(
this.config,
{ saving: true },
Expand Down

0 comments on commit 1323459

Please sign in to comment.