Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bugs due to pyflyby cell #20

Merged
merged 5 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ Support to run `tidy-imports` on a notebook.

- **Breaking**: Ported to JupyterLab 4.x

## [4.3.2](https://github.com/deshaw/jupyterlab-pyflyby/compare/v4.3.1...v4.3.2) (UNRELEASED)

### Fixed

- Fixed a bug where multiple clicks of the TidyImportsButton caused the notebook to be modified in unexpected ways. Some of these were -
- Outputs of cells being mismatched when reconstructing the notebook.
- Addition of random cells above and below the pyflyby tagged cell.
- Mutliple clicks of the TidyImportsButton would keep adding extra lines in the pyflyby cell.

## [4.3.1](https://github.com/deshaw/jupyterlab-pyflyby/compare/v4.3.0...v4.3.1) (2023-08-10)

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@deshaw/jupyterlab-pyflyby",
"version": "4.3.1",
"version": "4.3.2",
"description": "A labextension to integrate pyflyby with notebooks",
"keywords": [
"jupyter",
Expand Down
31 changes: 30 additions & 1 deletion src/cellUtils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { toArray } from '@lumino/algorithm';
import { MultilineString } from '@jupyterlab/nbformat';
import { ICellModel } from '@jupyterlab/cells';
import { PYFLYBY_END_MSG } from './constants';
import { PYFLYBY_END_MSG, PYFLYBY_START_MSG } from './constants';

// FIXME: There's got to be a better Typescript solution
// for distinguishing between members of a union type at runtime.
Expand Down Expand Up @@ -119,3 +119,32 @@ export const findLinePos = (cell: ICellModel): number => {
// These imports will be moved to next cell
return -1;
};

/**
* This code extracts non-imports lines from the pyflyby cell.
*
* @param cell - a cell model
*/
export const extractCodeFromPyflybyCell = (cell: ICellModel): string => {
const lines: string[] = normalizeMultilineString(cell.toJSON().source);

let stIdx = -1,
enIdx = -1;
for (let i = 0; i < lines.length; ++i) {
if (lines[i] === PYFLYBY_START_MSG.trim()) {
stIdx = i;
}
if (lines[i] === PYFLYBY_END_MSG.trim()) {
enIdx = i;
}
}

// we splice it twice to remove the pyflyby messages
const imports: string = lines
.splice(stIdx, enIdx - stIdx + 1)
.splice(stIdx + 1, enIdx - stIdx - 1)
.join();
const remainingCode: string = lines.join('');
console.log(imports, remainingCode);
return remainingCode;
};
58 changes: 48 additions & 10 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@

// Lumino imports
import { toArray, ArrayExt } from '@lumino/algorithm';
import { JSONValue, JSONObject } from '@lumino/coreutils';
import {
JSONValue,
JSONObject,
ReadonlyPartialJSONValue
} from '@lumino/coreutils';
import { Widget, Panel } from '@lumino/widgets';

// Jupyterlab imports
Expand All @@ -45,7 +49,7 @@ import { debug } from 'debug';
import React from 'react';

// relative imports
import { findCell, findLinePos } from './cellUtils';
import { extractCodeFromPyflybyCell, findCell, findLinePos } from './cellUtils';
import {
PYFLYBY_CELL_TAG,
PYFLYBY_START_MSG,
Expand Down Expand Up @@ -307,27 +311,61 @@ class PyflyByWidget extends Widget {
}

restoreNotebookAfterTidyImports(cellArray: any, imports: any): void {
const { cellIndex } = this._findAndSetImportCoordinates();
const cells = this._context.model.cells;
for (let i = 0; i < cellArray.length; ++i) {
const cell = cells.get(i);
cell.value.remove(0, cell.value.text.length);
cell.value.insert(0, cellArray[i].text.trim());
}
const joined_imports = imports.join('\n').trim();
if (cells.get(0).value.text.length === 0) {
cells.get(0).value.insert(0, joined_imports);
} else {
const joinedImports = imports.trim();
const { cellIndex } = this._findAndSetImportCoordinates();

const remainingCodeInPyflybyCell = extractCodeFromPyflybyCell(
cells.get(cellIndex)
);

if (remainingCodeInPyflybyCell !== '') {
// Remove import statements from the current pyflyby cell
cells
.get(cellIndex)
.value.remove(0, cells.get(cellIndex).value.text.length);

cells.get(cellIndex).value.insert(0, remainingCodeInPyflybyCell);

// remove the pyflyby cell tag from the current cell, we'll create another pyflyby cell
const tags: string[] = cells
.get(cellIndex)
.metadata.get('tags') as string[];
tags.splice(tags.indexOf(PYFLYBY_CELL_TAG));
cells
.get(cellIndex)
.metadata.set('tags', tags as ReadonlyPartialJSONValue);

// Create a new pyflyby cell and insert it at the top
const cell = this._context.model.contentFactory.createCodeCell({
cell: {
source: joined_imports,
source: [PYFLYBY_START_MSG, joinedImports, PYFLYBY_END_MSG].join(
'\n'
),
cell_type: 'code',
metadata: {
trusted: true
trusted: true,
tags: [PYFLYBY_CELL_TAG]
}
}
});
cells.insert(cellIndex, cell);

cells.insert(0, cell);
} else {
cells
.get(cellIndex)
.value.remove(0, cells.get(cellIndex).value.text.length);
cells
.get(cellIndex)
.value.insert(
0,
[PYFLYBY_START_MSG, joinedImports, PYFLYBY_END_MSG].join('\n')
);
}
}

Expand Down
Loading