GeezerVison is showing github.com — Check vars on execution count (#5214) · iserko/vscode-python@cb64ab2
File treeExpand file treeCollapse file tree Open diff view settings datascience-ui/history-react
Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboard +1Lines changed: 1 addition & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +Variable explorer handles new cell submissions |
Collapse file Copy file name to clipboardExpand all lines: pythonFiles/datascience/getJupyterVariableList.py +1-2Lines changed: 1 addition & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 12 | 12 | print(_VSCODE_json.dumps([{'name': var, | 13 | 13 | 'type': type(eval(var)).__name__, | 14 | 14 | 'size': _VSCODE_getsizeof(var), | 15 | | - 'supportsDataExplorer': type(eval(var)).__name__ in _VSCode_supportsDataExplorer, | 16 | | - 'expensive': True | | 15 | + 'supportsDataExplorer': type(eval(var)).__name__ in _VSCode_supportsDataExplorer | 17 | 16 | } for var in _VSCode_JupyterVars])) | 18 | 17 |
| 19 | 18 | del _VSCode_supportsDataExplorer | |
Collapse file Copy file name to clipboardExpand all lines: src/client/datascience/history/history.ts +7-2Lines changed: 7 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -228,7 +228,7 @@ export class History extends WebViewHost<IHistoryMapping> implements IHistory { | 228 | 228 | break; | 229 | 229 |
| 230 | 230 | case HistoryMessages.GetVariablesRequest: | 231 | | - this.requestVariables().ignoreErrors(); | | 231 | + this.requestVariables(payload).ignoreErrors(); | 232 | 232 | break; | 233 | 233 |
| 234 | 234 | case HistoryMessages.GetVariableValueRequest: | @@ -918,10 +918,15 @@ export class History extends WebViewHost<IHistoryMapping> implements IHistory { | 918 | 918 | } | 919 | 919 | } | 920 | 920 |
| 921 | | - private requestVariables = async (): Promise<void> => { | | 921 | + private requestVariables = async (executionCount: number): Promise<void> => { | 922 | 922 | // Request our new list of variables | 923 | 923 | let vars: IJupyterVariable[] = await this.jupyterVariables.getVariables(); | 924 | 924 |
| | 925 | + // Tag all of our jupyter variables with the execution count of the request | | 926 | + vars.forEach((value: IJupyterVariable) => { | | 927 | + value.executionCount = executionCount; | | 928 | + }); | | 929 | + | 925 | 930 | const settings = this.configuration.getSettings(); | 926 | 931 | const excludeString = settings.datascience.variableExplorerExclude; | 927 | 932 |
| |
Collapse file Copy file name to clipboardExpand all lines: src/client/datascience/history/historyTypes.ts +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -96,7 +96,7 @@ export class IHistoryMapping { | 96 | 96 | public [HistoryMessages.RemoteAddCode]: IRemoteAddCode; | 97 | 97 | public [HistoryMessages.Activate] : never | undefined; | 98 | 98 | public [HistoryMessages.ShowDataViewer]: string; | 99 | | - public [HistoryMessages.GetVariablesRequest]: never | undefined; | | 99 | + public [HistoryMessages.GetVariablesRequest]: number; | 100 | 100 | public [HistoryMessages.GetVariablesResponse]: IJupyterVariable[]; | 101 | 101 | public [HistoryMessages.GetVariableValueRequest]: IJupyterVariable; | 102 | 102 | public [HistoryMessages.GetVariableValueResponse]: IJupyterVariable; | |
Collapse file Copy file name to clipboardExpand all lines: src/client/datascience/types.ts +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -262,13 +262,13 @@ export interface IDataScienceExtraSettings extends IDataScienceSettings { | 262 | 262 | export interface IJupyterVariable { | 263 | 263 | name: string; | 264 | 264 | value: string | undefined; | | 265 | + executionCount?: number; | 265 | 266 | supportsDataExplorer: boolean; | 266 | 267 | type: string; | 267 | 268 | size: number; | 268 | 269 | shape: string; | 269 | 270 | count: number; | 270 | 271 | truncated: boolean; | 271 | | - expensive: boolean; | 272 | 272 | columns?: { key: string; type: string }[]; | 273 | 273 | rowCount?: number; | 274 | 274 | } | |
Collapse file Copy file name to clipboardExpand all lines: src/datascience-ui/history-react/MainPanel.tsx +27-11Lines changed: 27 additions & 11 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -35,6 +35,7 @@ export class MainPanel extends React.Component<IMainPanelProps, IMainPanelState> | 35 | 35 | private mainPanel: HTMLDivElement | null = null; | 36 | 36 | private variableExplorerRef: React.RefObject<VariableExplorer>; | 37 | 37 | private styleInjectorRef: React.RefObject<StyleInjector>; | | 38 | + private currentExecutionCount: number = 0; | 38 | 39 |
| 39 | 40 | // tslint:disable-next-line:max-func-body-length | 40 | 41 | constructor(props: IMainPanelProps, _state: IMainPanelState) { | @@ -667,8 +668,12 @@ export class MainPanel extends React.Component<IMainPanelProps, IMainPanelState> | 667 | 668 | } | 668 | 669 | } | 669 | 670 |
| | 671 | + // After the cell is finished update our current execution count | | 672 | + this.currentExecutionCount = this.getCurrentExecutionCount(this.state.cellVMs); | | 673 | + | 670 | 674 | // When a cell is finished refresh our variables | 671 | | - if (getSettings && getSettings().showJupyterVariableExplorer) { | | 675 | + // Use the ref here to maintain var explorer independence | | 676 | + if (this.variableExplorerRef.current && this.variableExplorerRef.current.state.open) { | 672 | 677 | this.refreshVariables(); | 673 | 678 | } | 674 | 679 | } | @@ -693,9 +698,14 @@ export class MainPanel extends React.Component<IMainPanelProps, IMainPanelState> | 693 | 698 | } | 694 | 699 | } | 695 | 700 |
| 696 | | - private getInputExecutionCount(cellVMs: ICellViewModel[]) : number { | | 701 | + // Check our list of cell vms to see what our current execution count is | | 702 | + private getCurrentExecutionCount = (cellVMs: ICellViewModel[]): number => { | 697 | 703 | const realCells = cellVMs.filter(c => c.cell.data.cell_type === 'code' && !c.editable && c.cell.data.execution_count); | 698 | | - return realCells && realCells.length > 0 ? parseInt(realCells[realCells.length - 1].cell.data.execution_count!.toString(), 10) + 1 : 1; | | 704 | + return realCells && realCells.length > 0 ? parseInt(realCells[realCells.length - 1].cell.data.execution_count!.toString(), 10) : 0; | | 705 | + } | | 706 | + | | 707 | + private getInputExecutionCount = (cellVMs: ICellViewModel[]) : number => { | | 708 | + return this.getCurrentExecutionCount(cellVMs) + 1; | 699 | 709 | } | 700 | 710 |
| 701 | 711 | private submitInput = (code: string) => { | @@ -747,7 +757,7 @@ export class MainPanel extends React.Component<IMainPanelProps, IMainPanelState> | 747 | 757 |
| 748 | 758 | // When the variable explorer wants to refresh state (say if it was expanded) | 749 | 759 | private refreshVariables = () => { | 750 | | - this.sendMessage(HistoryMessages.GetVariablesRequest); | | 760 | + this.sendMessage(HistoryMessages.GetVariablesRequest, this.currentExecutionCount); | 751 | 761 | } | 752 | 762 |
| 753 | 763 | // Find the display value for one specific variable | @@ -761,8 +771,11 @@ export class MainPanel extends React.Component<IMainPanelProps, IMainPanelState> | 761 | 771 | if (payload) { | 762 | 772 | const variable = payload as IJupyterVariable; | 763 | 773 |
| 764 | | - if (this.variableExplorerRef.current) { | 765 | | - this.variableExplorerRef.current.newVariableData(variable); | | 774 | + // Only send the updated variable data if we are on the same execution count as when we requsted it | | 775 | + if (variable && variable.executionCount !== undefined && variable.executionCount === this.currentExecutionCount) { | | 776 | + if (this.variableExplorerRef.current) { | | 777 | + this.variableExplorerRef.current.newVariableData(variable); | | 778 | + } | 766 | 779 | } | 767 | 780 | } | 768 | 781 | } | @@ -773,12 +786,15 @@ export class MainPanel extends React.Component<IMainPanelProps, IMainPanelState> | 773 | 786 | if (payload) { | 774 | 787 | const variables = payload as IJupyterVariable[]; | 775 | 788 |
| 776 | | - if (this.variableExplorerRef.current) { | 777 | | - this.variableExplorerRef.current.newVariablesData(variables); | 778 | | - } | | 789 | + // Check to see if we have moved to a new execution count only send our update if we are on the same count as the request | | 790 | + if (variables.length > 0 && variables[0].executionCount !== undefined && variables[0].executionCount === this.currentExecutionCount) { | | 791 | + if (this.variableExplorerRef.current) { | | 792 | + this.variableExplorerRef.current.newVariablesData(variables); | | 793 | + } | 779 | 794 |
| 780 | | - // Now put out a request for all of the sub values for the variables | 781 | | - variables.forEach(this.refreshVariable); | | 795 | + // Now put out a request for all of the sub values for the variables | | 796 | + variables.forEach(this.refreshVariable); | | 797 | + } | 782 | 798 | } | 783 | 799 | } | 784 | 800 | } |
Collapse file Copy file name to clipboardExpand all lines: src/datascience-ui/history-react/variableExplorer.tsx +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -54,7 +54,7 @@ export class VariableExplorer extends React.Component<IVariableExplorerProps, IV | 54 | 54 | {key: 'type', name: getLocString('DataScience.variableExplorerTypeColumn', 'Type'), type: 'string', width: 120}, | 55 | 55 | {key: 'size', name: getLocString('DataScience.variableExplorerSizeColumn', 'Size'), type: 'number', width: 120, formatter: <VariableExplorerCellFormatter cellStyle={CellStyle.numeric} />}, | 56 | 56 | {key: 'value', name: getLocString('DataScience.variableExplorerValueColumn', 'Value'), type: 'string', width: 300}, | 57 | | - {key: 'buttons', name: '', type: 'boolean', width: 32, formatter: <VariableExplorerButtonCellFormatter showDataExplorer={this.props.showDataExplorer} baseTheme={this.props.baseTheme} /> } | | 57 | + {key: 'buttons', name: '', type: 'boolean', width: 34, formatter: <VariableExplorerButtonCellFormatter showDataExplorer={this.props.showDataExplorer} baseTheme={this.props.baseTheme} /> } | 58 | 58 | ]; | 59 | 59 | this.state = { open: false, | 60 | 60 | gridColumns: columns, | |
Collapse file Copy file name to clipboardExpand all lines: src/datascience-ui/history-react/variableExplorerGrid.scss +3-3Lines changed: 3 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 36 | 36 | #variable-explorer-data-grid .react-grid-HeaderCell { | 37 | 37 | background-color: var(--vscode-editor-lineHighlightBorder); | 38 | 38 | color: var(--vscode-editor-foreground); | 39 | | - border-style: none none solid none; | 40 | | - border-bottom-color: var(--vscode-badge-background); | 41 | | - padding: 4px; | | 39 | + border-style: solid; | | 40 | + border-color: var(--vscode-badge-background); | | 41 | + padding: 2px; | 42 | 42 | } | 43 | 43 |
| 44 | 44 |
| |
Collapse file Copy file name to clipboardExpand all lines: src/test/datascience/jupyterVariables.unit.test.ts +11-11Lines changed: 11 additions & 11 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -75,7 +75,7 @@ suite('JupyterVariables', () => { | 75 | 75 |
| 76 | 76 | fakeServer.setup(fs => fs.execute(typemoq.It.isAny(), typemoq.It.isAny(), typemoq.It.isAny(), typemoq.It.isAny(), undefined, typemoq.It.isAny())) | 77 | 77 | .returns(() => Promise.resolve(generateCells( | 78 | | - '[{"name": "big_dataframe", "type": "DataFrame", "size": 62, "expensive": true}, {"name": "big_dict", "type": "dict", "size": 57, "expensive": true}, {"name": "big_float", "type": "float", "size": 58, "expensive": true}, {"name": "big_int", "type": "int", "size": 56, "expensive": true}, {"name": "big_list", "type": "list", "size": 57, "expensive": true}, {"name": "big_nparray", "type": "ndarray", "size": 60, "expensive": true}, {"name": "big_series", "type": "Series", "size": 59, "expensive": true}, {"name": "big_string", "type": "str", "size": 59, "expensive": true}, {"name": "big_tuple", "type": "tuple", "size": 58, "expensive": true}]', | | 78 | + '[{"name": "big_dataframe", "type": "DataFrame", "size": 62}, {"name": "big_dict", "type": "dict", "size": 57}, {"name": "big_float", "type": "float", "size": 58}, {"name": "big_int", "type": "int", "size": 56}, {"name": "big_list", "type": "list", "size": 57}, {"name": "big_nparray", "type": "ndarray", "size": 60}, {"name": "big_series", "type": "Series", "size": 59}, {"name": "big_string", "type": "str", "size": 59}, {"name": "big_tuple", "type": "tuple", "size": 58]', | 79 | 79 | 'stream' | 80 | 80 | ))) | 81 | 81 | .verifiable(typemoq.Times.never()); | @@ -157,7 +157,7 @@ suite('JupyterVariables', () => { | 157 | 157 |
| 158 | 158 | fakeServer.setup(fs => fs.execute(typemoq.It.isValue('test'), typemoq.It.isValue(Identifiers.EmptyFileName), typemoq.It.isValue(0), typemoq.It.isAnyString(), undefined, typemoq.It.isValue(true))) | 159 | 159 | .returns(() => Promise.resolve(generateCells( | 160 | | - '[{"name": "big_dataframe", "type": "DataFrame", "size": 62, "expensive": true}, {"name": "big_dict", "type": "dict", "size": 57, "expensive": true}, {"name": "big_int", "type": "int", "size": 56, "expensive": true}, {"name": "big_list", "type": "list", "size": 57, "expensive": true}, {"name": "big_nparray", "type": "ndarray", "size": 60, "expensive": true}, {"name": "big_string", "type": "str", "size": 59, "expensive": true}]', | | 160 | + '[{"name": "big_dataframe", "type": "DataFrame", "size": 62}, {"name": "big_dict", "type": "dict", "size": 57}, {"name": "big_int", "type": "int", "size": 56}, {"name": "big_list", "type": "list", "size": 57}, {"name": "big_nparray", "type": "ndarray", "size": 60}, {"name": "big_string", "type": "str", "size": 59}]', | 161 | 161 | 'stream' | 162 | 162 | ))) | 163 | 163 | .verifiable(typemoq.Times.once()); | @@ -168,12 +168,12 @@ suite('JupyterVariables', () => { | 168 | 168 | assert.equal(results.length, 6); | 169 | 169 |
| 170 | 170 | // Check our items (just the first few real items, no need to check all 19) | 171 | | - assert.deepEqual(results[0], {name: 'big_dataframe', size: 62, type: 'DataFrame', expensive: true}); | 172 | | - assert.deepEqual(results[1], {name: 'big_dict', size: 57, type: 'dict', expensive: true}); | 173 | | - assert.deepEqual(results[2], {name: 'big_int', size: 56, type: 'int', expensive: true}); | 174 | | - assert.deepEqual(results[3], {name: 'big_list', size: 57, type: 'list', expensive: true}); | 175 | | - assert.deepEqual(results[4], {name: 'big_nparray', size: 60, type: 'ndarray', expensive: true}); | 176 | | - assert.deepEqual(results[5], {name: 'big_string', size: 59, type: 'str', expensive: true}); | | 171 | + assert.deepEqual(results[0], {name: 'big_dataframe', size: 62, type: 'DataFrame'}); | | 172 | + assert.deepEqual(results[1], {name: 'big_dict', size: 57, type: 'dict'}); | | 173 | + assert.deepEqual(results[2], {name: 'big_int', size: 56, type: 'int'}); | | 174 | + assert.deepEqual(results[3], {name: 'big_list', size: 57, type: 'list'}); | | 175 | + assert.deepEqual(results[4], {name: 'big_nparray', size: 60, type: 'ndarray'}); | | 176 | + assert.deepEqual(results[5], {name: 'big_string', size: 59, type: 'str'}); | 177 | 177 |
| 178 | 178 | fakeServer.verifyAll(); | 179 | 179 | }); | @@ -186,17 +186,17 @@ suite('JupyterVariables', () => { | 186 | 186 |
| 187 | 187 | fakeServer.setup(fs => fs.execute(typemoq.It.isValue('test'), typemoq.It.isValue(Identifiers.EmptyFileName), typemoq.It.isValue(0), typemoq.It.isAnyString(), undefined, typemoq.It.isValue(true))) | 188 | 188 | .returns(() => Promise.resolve(generateCells( | 189 | | - '{"name": "big_complex", "type": "complex", "size": 60, "expensive": true, "value": "(1+1j)"}', | | 189 | + '{"name": "big_complex", "type": "complex", "size": 60, "value": "(1+1j)"}', | 190 | 190 | 'stream' | 191 | 191 | ))) | 192 | 192 | .verifiable(typemoq.Times.once()); | 193 | 193 |
| 194 | | - const testVariable: IJupyterVariable = { name: 'big_complex', type: 'complex', size: 60, expensive: true, truncated: false, count: 0, shape: '', value: '', supportsDataExplorer: false }; | | 194 | + const testVariable: IJupyterVariable = { name: 'big_complex', type: 'complex', size: 60, truncated: false, count: 0, shape: '', value: '', supportsDataExplorer: false }; | 195 | 195 |
| 196 | 196 | const resultVariable = await jupyterVariables.getValue(testVariable); | 197 | 197 |
| 198 | 198 | // Verify the result value should be filled out from fake server result | 199 | | - assert.deepEqual(resultVariable, {name: 'big_complex', size: 60, type: 'complex', expensive: true, value: '(1+1j)'}); | | 199 | + assert.deepEqual(resultVariable, {name: 'big_complex', size: 60, type: 'complex', value: '(1+1j)'}); | 200 | 200 | fakeServer.verifyAll(); | 201 | 201 | }); | 202 | 202 | }); |
|