Skip to content
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
6 changes: 3 additions & 3 deletions pythonFiles/datascience/getJupyterVariableValue.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ def __call__(self, obj):
return ''.join((x.encode('utf-8') if isinstance(x, unicode) else x) for x in self._repr(obj, 0))
else:
return ''.join(self._repr(obj, 0))
except Exception:
except Exception as e:
try:
return 'An exception was raised: %r' % sys.exc_info()[1]
return 'An exception was raised: ' + str(e)
except Exception:
return 'An exception was raised'

Expand Down Expand Up @@ -373,7 +373,7 @@ def _bytes_as_unicode_if_possible(self, obj_repr):
# locale.getpreferredencoding() and 'utf-8). If no encoding can decode
# the input, we return the original bytes.
try_encodings = []
encoding = self.sys_stdout_encoding or getattr(sys.stdout, 'encoding', '')
encoding = self.sys_stdout_encoding or getattr(VC_sys.stdout, 'encoding', '')
if encoding:
try_encodings.append(encoding.lower())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export namespace InteractiveWindowMessages {
export const NotebookClean = 'clean';
export const SaveAll = 'save_all';
export const NativeCommand = 'native_command';
export const VariablesComplete = 'variables_complete';

}

Expand Down Expand Up @@ -301,4 +302,5 @@ export class IInteractiveWindowMapping {
public [InteractiveWindowMessages.NotebookClean]: never | undefined;
public [InteractiveWindowMessages.SaveAll]: ISaveAll;
public [InteractiveWindowMessages.NativeCommand]: INativeCommand;
public [InteractiveWindowMessages.VariablesComplete]: never | undefined;
}
7 changes: 7 additions & 0 deletions src/datascience-ui/interactive-common/mainStateController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,8 @@ export class MainStateController implements IMessageHandler {
}

public renderUpdate(newState: {}) {
const oldCount = this.state.pendingVariableCount;

// This method should be called during the render stage of anything
// using this state Controller. That's because after shouldComponentUpdate
// render is next and at this point the state has been set.
Expand All @@ -648,6 +650,11 @@ export class MainStateController implements IMessageHandler {
if ('cellVMs' in newState) {
this.sendInfo();
}

// If the new state includes pendingVariableCount and it's gone to zero, send a message
if (this.state.pendingVariableCount === 0 && oldCount !== 0) {
setTimeout(() => this.sendMessage(InteractiveWindowMessages.VariablesComplete), 1);
}
}

public getState(): IMainState {
Expand Down
2 changes: 1 addition & 1 deletion src/test/datascience/nativeEditor.functional.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ for _ in range(50):
await addCell(wrapper, matPlotLib, true, 5);
verifyHtmlOnCell(wrapper, 'NativeCell', matPlotLibResults, CellPosition.Last);

await addCell(wrapper, spinningCursor, true, 3 + (ioc.mockJupyter ? (cursors.length * 3) : 0));
await addCell(wrapper, spinningCursor, true, 3 + (ioc.mockJupyter ? (cursors.length * 3) : 50));
verifyHtmlOnCell(wrapper, 'NativeCell', '<div>', CellPosition.Last);
}, () => { return ioc; });

Expand Down
50 changes: 24 additions & 26 deletions src/test/datascience/variableexplorer.functional.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { parse } from 'node-html-parser';
import * as React from 'react';
import { Disposable } from 'vscode';

import { InteractiveWindowMessages } from '../../client/datascience/interactive-common/interactiveWindowTypes';
import { IJupyterVariable } from '../../client/datascience/types';
import { InteractivePanel } from '../../datascience-ui/history-react/interactivePanel';
import { VariableExplorer } from '../../datascience-ui/interactive-common/variableExplorer';
Expand All @@ -16,7 +17,7 @@ import { DataScienceIocContainer } from './dataScienceIocContainer';
import { addCode } from './interactiveWindowTestHelpers';
import { addCell, createNewEditor } from './nativeEditorTestHelpers';
import { waitForUpdate } from './reactHelpers';
import { runDoubleTest } from './testHelpers';
import { runDoubleTest, waitForMessage } from './testHelpers';

// tslint:disable:max-func-body-length trailing-comma no-any no-multiline-string
suite('DataScience Interactive Window variable explorer tests', () => {
Expand Down Expand Up @@ -60,10 +61,17 @@ suite('DataScience Interactive Window variable explorer tests', () => {
// asyncDump();
//});

async function addCodeImpartial(wrapper: ReactWrapper<any, Readonly<{}>, React.Component>, code: string, expectedRenderCount: number = 4, expectError: boolean = false): Promise<ReactWrapper<any, Readonly<{}>, React.Component>> {
async function waitForVariablesUpdated(): Promise<void> {
return waitForMessage(ioc, InteractiveWindowMessages.VariablesComplete);
}

async function addCodeImpartial(wrapper: ReactWrapper<any, Readonly<{}>, React.Component>, code: string, waitForVariables: boolean = true, expectedRenderCount: number = 4, expectError: boolean = false): Promise<ReactWrapper<any, Readonly<{}>, React.Component>> {
const variablesUpdated = waitForVariables ? waitForVariablesUpdated() : Promise.resolve();
const nodes = wrapper.find('InteractivePanel');
if (nodes.length > 0) {
return addCode(ioc, wrapper, code, expectedRenderCount, expectError);
const result = await addCode(ioc, wrapper, code, expectedRenderCount, expectError);
await variablesUpdated;
return result;
} else {
// For the native editor case, we need to create an editor before hand.
if (!createdNotebook) {
Expand All @@ -72,6 +80,7 @@ suite('DataScience Interactive Window variable explorer tests', () => {
expectedRenderCount += 1;
}
await addCell(wrapper, code, true, expectedRenderCount);
await variablesUpdated;
return wrapper;
}
}
Expand All @@ -85,8 +94,7 @@ value = 'hello world'`;
openVariableExplorer(wrapper);

await addCodeImpartial(wrapper, 'a=1\na');
await addCodeImpartial(wrapper, basicCode, 4);
await waitForUpdate(wrapper, VariableExplorer, 3);
await addCodeImpartial(wrapper, basicCode, true, 4);

// We should show a string and show an int, the modules should be hidden
let targetVariables: IJupyterVariable[] = [
Expand All @@ -100,8 +108,7 @@ value = 'hello world'`;
ioc.getSettings().datascience.variableExplorerExclude = `${ioc.getSettings().datascience.variableExplorerExclude};str`;

// Add another string and check our vars, strings should be hidden
await addCodeImpartial(wrapper, basicCode2, 4);
await waitForUpdate(wrapper, VariableExplorer, 2);
await addCodeImpartial(wrapper, basicCode2, true, 4);

targetVariables = [
{name: 'a', value: '1', supportsDataExplorer: false, type: 'int', size: 54, shape: '', count: 0, truncated: false}
Expand All @@ -116,7 +123,6 @@ value = 'hello world'`;
openVariableExplorer(wrapper);

await addCodeImpartial(wrapper, 'a=1\na');
await waitForUpdate(wrapper, VariableExplorer, 2);

// Check that we have just the 'a' variable
let targetVariables: IJupyterVariable[] = [
Expand All @@ -125,8 +131,7 @@ value = 'hello world'`;
verifyVariables(wrapper, targetVariables);

// Add another variable and check it
await addCodeImpartial(wrapper, basicCode, 4);
await waitForUpdate(wrapper, VariableExplorer, 3);
await addCodeImpartial(wrapper, basicCode, true, 4);

targetVariables = [
{name: 'a', value: '1', supportsDataExplorer: false, type: 'int', size: 54, shape: '', count: 0, truncated: false},
Expand All @@ -136,8 +141,7 @@ value = 'hello world'`;
verifyVariables(wrapper, targetVariables);

// Add a second variable and check it
await addCodeImpartial(wrapper, basicCode2, 4);
await waitForUpdate(wrapper, VariableExplorer, 4);
await addCodeImpartial(wrapper, basicCode2, true, 4);

targetVariables = [
{name: 'a', value: '1', supportsDataExplorer: false, type: 'int', size: 54, shape: '', count: 0, truncated: false},
Expand All @@ -155,7 +159,7 @@ value = 'hello world'`;
openVariableExplorer(wrapper);

await addCodeImpartial(wrapper, 'a=1\na');
await addCodeImpartial(wrapper, basicCode, 4);
await addCodeImpartial(wrapper, basicCode, false, 4);

// Here we are only going to wait for two renders instead of the needed three
// a should have the value updated, but value should still be loading
Expand Down Expand Up @@ -187,11 +191,7 @@ myDict = {'a': 1}`;
openVariableExplorer(wrapper);

await addCodeImpartial(wrapper, 'a=1\na');
await addCodeImpartial(wrapper, basicCode, 4);

// Verify that we actually update the variable explorer
// Count here is our main render + a render for each variable row as they come in
await waitForUpdate(wrapper, VariableExplorer, 5);
await addCodeImpartial(wrapper, basicCode, true, 4);

const targetVariables: IJupyterVariable[] = [
{name: 'a', value: '1', supportsDataExplorer: false, type: 'int', size: 54, shape: '', count: 0, truncated: false},
Expand Down Expand Up @@ -219,11 +219,7 @@ myTuple = 1,2,3,4,5,6,7,8,9
openVariableExplorer(wrapper);

await addCodeImpartial(wrapper, 'a=1\na');
await addCodeImpartial(wrapper, basicCode, 4);

// Verify that we actually update the variable explorer
// Count here is our main render + a render for each variable row as they come in
await waitForUpdate(wrapper, VariableExplorer, 9);
await addCodeImpartial(wrapper, basicCode, true, 4);

const targetVariables: IJupyterVariable[] = [
{name: 'a', value: '1', supportsDataExplorer: false, type: 'int', size: 54, shape: '', count: 0, truncated: false},
Expand Down Expand Up @@ -255,9 +251,7 @@ strc = 'c'`;
openVariableExplorer(wrapper);

await addCodeImpartial(wrapper, 'a=1\na');
await addCodeImpartial(wrapper, basicCode, 4);

await waitForUpdate(wrapper, VariableExplorer, 7);
await addCodeImpartial(wrapper, basicCode, true, 4);

let targetVariables: IJupyterVariable[] = [
{name: 'a', value: '1', supportsDataExplorer: false, type: 'int', size: 54, shape: '', count: 0, truncated: false},
Expand Down Expand Up @@ -318,6 +312,10 @@ function sortVariableExplorer(wrapper: ReactWrapper<any, Readonly<{}>, React.Com

// Verify a set of rows versus a set of expected variables
function verifyVariables(wrapper: ReactWrapper<any, Readonly<{}>, React.Component>, targetVariables: IJupyterVariable[]) {
// Force an update so we render whatever the current state is
wrapper.update();

// Then search for results.
const foundRows = wrapper.find('div.react-grid-Row');

expect(foundRows.length).to.be.equal(targetVariables.length, 'Different number of variable explorer rows and target variables');
Expand Down