Skip to content

Refactored exporting notebooks to python script #12232

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

Merged
merged 61 commits into from
Jun 15, 2020

Conversation

techwithtim
Copy link

@techwithtim techwithtim commented Jun 9, 2020

For #

This PR added the necessary infrastructure for exporting python files to different formats (specifically PDF and HTML). It also includes the implementation of exporting to python script which works as before, it has just been rewritten.

NOTE: Telemetry and more tests will be added in a future PR.

@techwithtim will continue to work on this and add implementations for export to PDF and HTML in the coming days.

  • Pull request represents a single change (i.e. not fixing disparate/unrelated things in a single PR).
  • Title summarizes what is changing.
  • Has a news entry file (remember to thank yourself!).
  • Appropriate comments and documentation strings in the code.
  • Has sufficient logging.
  • Has telemetry for enhancements.
  • Unit tests & system/integration tests are added/updated.
  • Test plan is updated as appropriate.
  • package-lock.json has been regenerated by running npm install (if dependencies have changed).
  • The wiki is updated with any design decisions/details.

@techwithtim techwithtim added the no-changelog No news entry required label Jun 9, 2020
@techwithtim techwithtim self-assigned this Jun 9, 2020
@techwithtim techwithtim marked this pull request as draft June 9, 2020 19:37
Copy link

@rchiodo rchiodo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🕐

@techwithtim techwithtim changed the title Added infrastructure for exporting notebooks to different formats - Export to Python Script is still working is working Added infrastructure for exporting notebooks to different formats - Export to Python Script is still working Jun 9, 2020
tempFile.dispose();
}
status.dispose();
private async exportAs(): Promise<void> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you need this equivalent function in the interactive window.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've left the current export method in interactive window for now. Can't remember exactly why but I think interactive window behaves differently so I didn't change it. Here's what the function in interactive window looks like:

@captureTelemetry(Telemetry.ExportNotebook, undefined, false)
    // tslint:disable-next-line: no-any no-empty
    private async export(cells: ICell[]) {
        // Should be an array of cells
        if (cells && this.applicationShell) {
            // Indicate busy
            this.startProgress();
            try {
                const filtersKey = localize.DataScience.exportDialogFilter();
                const filtersObject: Record<string, string[]> = {};
                filtersObject[filtersKey] = ['ipynb'];

                // Bring up the open file dialog box
                const uri = await this.applicationShell.showSaveDialog({
                    saveLabel: localize.DataScience.exportDialogTitle(),
                    filters: filtersObject
                });
                if (uri) {
                    await this.jupyterExporter.exportToFile(cells, uri.fsPath);
                }
            } finally {
                this.stopProgress();
            }
        }
    }

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like it should work the same though. I think people would want export to pdf/html for the interactive window too. Oh, 1 difference. Interactive exports to ipynb. Native exports to .py file.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we should wire it up before we're all done though.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meaning this PR seems okay for this.

const activeTextEditorChange = createDeferred();
const docManager = ioc.get<IDocumentManager>(IDocumentManager) as MockDocumentManager;
docManager.onDidChangeActiveTextEditor(() => activeTextEditorChange.resolve());
const commandFired = createDeferred();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like the test isn't actually testing export anymore. It looks like it's just testing that the command fires. This should still work without having to rewire the command manager. Perhaps the arguments aren't getting passed around?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not pass these test without doing this. Don and I worked on it, I'll wait for his feedback here @DonJayamanne

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can help debug if you like. This test should be pretty straightforward to debug what's happening.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a separate test for exporting a ipynb to python file and opening it as well.
That's an end to end test, just not testing from here.
This way, we don't need to write such a test again for native notebook or interactive window.

I.e. here we validate whether command is called.
In another place we test exporting.

Please see here (super simple test) https://github.com/microsoft/vscode-python/pull/12232/files/12ec2072888b3f75aa8a2f24d39677cfe3020ead#diff-0135d4b7cc537d39be915ab50526a81a

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That commit doesn't work. Where's the other end to end export test?


In reply to: 439532742 [](ancestors = 439532742)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's an export test for the interactive window. (notebook.functional.tests.ts), but I don't see one for convert to python.


In reply to: 440325263 [](ancestors = 440325263,439532742)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/test/datascience/export/exportManagerFileOpener.unit.test.ts
src/test/datascience/export/exportToPython.test.ts

Did you see those?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope didn't notice those. Theoretically there could be a disconnect between the command being handled and the actual export happening, but the sum of those tests and this one do test all of the code. However you could eliminate those other tests if you got this one working end to end. And then we'd have a true end to end on export. Does that not sound better?


In reply to: 440343334 [](ancestors = 440343334)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does sound better. Can that wait for another PR? I'm planning on adding more tests and other enhancements in future PR's

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, no problem.


In reply to: 440354406 [](ancestors = 440354406)

@DonJayamanne DonJayamanne marked this pull request as ready for review June 12, 2020 16:45
@DonJayamanne DonJayamanne changed the title Added infrastructure for exporting notebooks to different formats - Export to Python Script is still working WIP - Added infrastructure for exporting notebooks to different formats - Export to Python Script is still working Jun 12, 2020

export const IExportManagerFilePicker = Symbol('IExportManagerFilePicker');
export interface IExportManagerFilePicker {
getExportFileLocation(format: ExportFormat): Promise<Uri | undefined>;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
getExportFileLocation(format: ExportFormat): Promise<Uri | undefined>;
getExportFileLocation(model:INotebookModel, format: ExportFormat): Promise<Uri | undefined>;

Personally I'd prefer to pass in the file that's being exported.
This way when we display the save dialog we can generate a file based on the existing name.
E.g. if the nb is pytorch.ipynb, i'd expect the save diaglog to default the file name to pytorch.pdf (if format is pdf).

Oh yes, generally I'd see a custom title in the save diaglog such as Export pytorch.ipyn to PDF or the like..

const activeTextEditorChange = createDeferred();
const docManager = ioc.get<IDocumentManager>(IDocumentManager) as MockDocumentManager;
docManager.onDidChangeActiveTextEditor(() => activeTextEditorChange.resolve());
const commandFired = createDeferred();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a separate test for exporting a ipynb to python file and opening it as well.
That's an end to end test, just not testing from here.
This way, we don't need to write such a test again for native notebook or interactive window.

I.e. here we validate whether command is called.
In another place we test exporting.

Please see here (super simple test) https://github.com/microsoft/vscode-python/pull/12232/files/12ec2072888b3f75aa8a2f24d39677cfe3020ead#diff-0135d4b7cc537d39be915ab50526a81a

@sonarqubecloud
Copy link

Kudos, SonarCloud Quality Gate passed!

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities (and Security Hotspot 0 Security Hotspots to review)
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

@techwithtim techwithtim changed the title WIP - Added infrastructure for exporting notebooks to different formats - Export to Python Script is still working Refactored exporting notebooks to python script Jun 15, 2020
Copy link

@rchiodo rchiodo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

ignoreFocusOut: false,
matchOnDescription: true,
matchOnDetail: true,
placeHolder: 'Export As...'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be localized.

return;
}

const notebookFileName = stripFileExtension(path.basename(source.fsPath));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use path.basename(soruce.fsPath, path.extname(source.fsapat))
Pass the second argument into path.basename

this.defaultExportSaveLocation
);

return Uri.file(filePath);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What will happen if a user exports a python file for the first time?
Will this code exist?


private updateFileSaveLocation(value: Uri) {
const location = path.dirname(value.fsPath);
this.workspaceStorage.update(ExportNotebookSettings.lastSaveLocation, location);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is async code, you need an await here.

@techwithtim techwithtim merged commit e121d5a into microsoft:master Jun 15, 2020
@techwithtim techwithtim deleted the export branch June 15, 2020 18:33
@lock lock bot locked as resolved and limited conversation to collaborators Jun 24, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
no-changelog No news entry required
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants