diff --git a/build/ci/templates/globals.yml b/build/ci/templates/globals.yml index 1303ba0bc8e6..42542c5f78c9 100644 --- a/build/ci/templates/globals.yml +++ b/build/ci/templates/globals.yml @@ -8,4 +8,4 @@ variables: VSC_PYTHON_LOG_FILE: '$(Build.ArtifactStagingDirectory)/pvsc.log' CI_BRANCH_NAME: ${Build.SourceBranchName} npm_config_cache: $(Pipeline.Workspace)/.npm - + vmImageMacOS: 'macOS-10.15' diff --git a/build/ci/vscode-python-ci-manual.yaml b/build/ci/vscode-python-ci-manual.yaml index dab4e97f07a4..21a67ef23bb9 100644 --- a/build/ci/vscode-python-ci-manual.yaml +++ b/build/ci/vscode-python-ci-manual.yaml @@ -168,7 +168,7 @@ stages: NeedsIPythonReqs: true #maxParallel: 3 pool: - vmImage: 'macos-10.13' + vmImage: '$(vmImageMacOS)' steps: - template: templates/test_phases.yml @@ -205,7 +205,7 @@ stages: NeedsPythonTestReqs: true #maxParallel: 3 pool: - vmImage: 'macos-10.13' + vmImage: '$(vmImageMacOS)' steps: - template: templates/test_phases.yml diff --git a/build/ci/vscode-python-ci.yaml b/build/ci/vscode-python-ci.yaml index fc1cae3c0cb9..7cfd8ee4006a 100644 --- a/build/ci/vscode-python-ci.yaml +++ b/build/ci/vscode-python-ci.yaml @@ -140,7 +140,7 @@ stages: NeedsIPythonReqs: true maxParallel: 2 pool: - vmImage: 'macos-10.13' + vmImage: '$(vmImageMacOS)' steps: - template: templates/test_phases.yml diff --git a/build/ci/vscode-python-nightly-ci.yaml b/build/ci/vscode-python-nightly-ci.yaml index 50395a6fc494..49b94db2e7a3 100644 --- a/build/ci/vscode-python-nightly-ci.yaml +++ b/build/ci/vscode-python-nightly-ci.yaml @@ -224,7 +224,7 @@ stages: NeedsIPythonReqs: true maxParallel: 1 pool: - vmImage: 'macos-10.13' + vmImage: '$(vmImageMacOS)' steps: - template: templates/test_phases.yml @@ -264,7 +264,7 @@ stages: # Note: We only run the smoke tests with the latest Python release. maxParallel: 1 pool: - vmImage: 'macos-10.13' + vmImage: '$(vmImageMacOS)' steps: - template: templates/test_phases.yml @@ -304,7 +304,7 @@ stages: # Note: We only run the smoke tests with the latest Python release. maxParallel: 1 pool: - vmImage: 'macos-10.13' + vmImage: '$(vmImageMacOS)' steps: - template: templates/test_phases.yml @@ -340,7 +340,7 @@ stages: # Note: We only run the smoke tests with the latest Python release. maxParallel: 1 pool: - vmImage: 'macos-10.13' + vmImage: '$(vmImageMacOS)' steps: - template: templates/test_phases.yml diff --git a/build/ci/vscode-python-nightly-flake-ci.yaml b/build/ci/vscode-python-nightly-flake-ci.yaml index 191e3503a3ea..d9a749d90e59 100644 --- a/build/ci/vscode-python-nightly-flake-ci.yaml +++ b/build/ci/vscode-python-nightly-flake-ci.yaml @@ -81,7 +81,7 @@ stages: NeedsPythonFunctionalReqs: true VSCODE_PYTHON_ROLLING: true pool: - vmImage: 'macos-10.13' + vmImage: '$(vmImageMacOS)' steps: - template: templates/test_phases.yml @@ -97,7 +97,7 @@ stages: NeedsPythonFunctionalReqs: true VSCODE_PYTHON_ROLLING: true pool: - vmImage: 'macos-10.13' + vmImage: '$(vmImageMacOS)' steps: - template: templates/test_phases.yml @@ -134,4 +134,4 @@ stages: pool: vmImage: 'vs2017-win2016' steps: - - template: templates/test_phases.yml \ No newline at end of file + - template: templates/test_phases.yml diff --git a/build/ci/vscode-python-pr-validation.yaml b/build/ci/vscode-python-pr-validation.yaml index fd143602a23b..cca59086d64a 100644 --- a/build/ci/vscode-python-pr-validation.yaml +++ b/build/ci/vscode-python-pr-validation.yaml @@ -86,7 +86,7 @@ stages: NeedsPythonTestReqs: true NeedsPythonFunctionalReqs: true pool: - vmImage: 'macos-10.13' + vmImage: '$(vmImageMacOS)' steps: - template: templates/test_phases.yml diff --git a/news/2 Fixes/10137.md b/news/2 Fixes/10137.md new file mode 100644 index 000000000000..47419ce382a2 --- /dev/null +++ b/news/2 Fixes/10137.md @@ -0,0 +1 @@ +Fix scrolling for output to consistently scroll even during execution. \ No newline at end of file diff --git a/news/2 Fixes/10204.md b/news/2 Fixes/10204.md new file mode 100644 index 000000000000..8456ecbf29c5 --- /dev/null +++ b/news/2 Fixes/10204.md @@ -0,0 +1 @@ +Fix empty variables to show an empty string in the Notebook/Interactive Window variable explorer. \ No newline at end of file diff --git a/news/2 Fixes/9935.md b/news/2 Fixes/9935.md new file mode 100644 index 000000000000..d80250f6b9b6 --- /dev/null +++ b/news/2 Fixes/9935.md @@ -0,0 +1 @@ +Switching kernels should disable the run/interrupt/restart buttons. \ No newline at end of file diff --git a/news/2 Fixes/9959.md b/news/2 Fixes/9959.md new file mode 100644 index 000000000000..40f534911697 --- /dev/null +++ b/news/2 Fixes/9959.md @@ -0,0 +1 @@ +Support opening spark dataframes in the data viewer. \ No newline at end of file diff --git a/news/3 Code Health/10288.md b/news/3 Code Health/10288.md new file mode 100644 index 000000000000..ea1ff2246a3d --- /dev/null +++ b/news/3 Code Health/10288.md @@ -0,0 +1 @@ +Use new MacOS VM in Pipelines. diff --git a/pythonFiles/datascience/getJupyterVariableDataFrameInfo.py b/pythonFiles/datascience/getJupyterVariableDataFrameInfo.py index 2447132ab8bd..6a2a2bba9a0f 100644 --- a/pythonFiles/datascience/getJupyterVariableDataFrameInfo.py +++ b/pythonFiles/datascience/getJupyterVariableDataFrameInfo.py @@ -10,6 +10,22 @@ # Indexes off of _VSCODE_targetVariable need to index types that are part of IJupyterVariable _VSCODE_targetVariable = _VSCODE_json.loads("""_VSCode_JupyterTestValue""") +# Function to compute row count for a value +def _VSCODE_getRowCount(var): + if hasattr(var, "shape"): + try: + # Get a bit more restrictive with exactly what we want to count as a shape, since anything can define it + if isinstance(var.shape, tuple): + return var.shape[0] + except TypeError: + return 0 + elif hasattr(var, "__len__"): + try: + return len(var) + except TypeError: + return 0 + + # First check to see if we are a supported type, this prevents us from adding types that are not supported # and also keeps our types in sync with what the variable explorer says that we support if _VSCODE_targetVariable["type"] not in _VSCode_supportsDataExplorer: @@ -21,18 +37,7 @@ _VSCODE_evalResult = eval(_VSCODE_targetVariable["name"]) # Figure out shape if not already there. Use the shape to compute the row count - if hasattr(_VSCODE_evalResult, "shape"): - try: - # Get a bit more restrictive with exactly what we want to count as a shape, since anything can define it - if isinstance(_VSCODE_evalResult.shape, tuple): - _VSCODE_targetVariable["rowCount"] = _VSCODE_evalResult.shape[0] - except TypeError: - _VSCODE_targetVariable["rowCount"] = 0 - elif hasattr(_VSCODE_evalResult, "__len__"): - try: - _VSCODE_targetVariable["rowCount"] = len(_VSCODE_evalResult) - except TypeError: - _VSCODE_targetVariable["rowCount"] = 0 + _VSCODE_targetVariable["rowCount"] = _VSCODE_getRowCount(_VSCODE_evalResult) # Turn the eval result into a df _VSCODE_df = _VSCODE_evalResult @@ -45,6 +50,9 @@ _VSCODE_df = _VSCODE_pd.Series.to_frame(_VSCODE_evalResult) elif _VSCODE_targetVariable["type"] == "ndarray": _VSCODE_df = _VSCODE_pd.DataFrame(_VSCODE_evalResult) + elif hasattr(_VSCODE_df, "toPandas"): + _VSCODE_df = _VSCODE_df.toPandas() + _VSCODE_targetVariable["rowCount"] = _VSCODE_getRowCount(_VSCODE_df) # If any rows, use pandas json to convert a single row to json. Extract # the column names and types from the json so we match what we'll fetch when diff --git a/pythonFiles/datascience/getJupyterVariableDataFrameRows.py b/pythonFiles/datascience/getJupyterVariableDataFrameRows.py index 7bf647f652ae..697cc14ad1b6 100644 --- a/pythonFiles/datascience/getJupyterVariableDataFrameRows.py +++ b/pythonFiles/datascience/getJupyterVariableDataFrameRows.py @@ -24,6 +24,8 @@ _VSCODE_df = _VSCODE_pd.Series.to_frame(_VSCODE_evalResult) elif _VSCODE_targetVariable["type"] == "ndarray": _VSCODE_df = _VSCODE_pd.DataFrame(_VSCODE_evalResult) +elif hasattr(_VSCODE_df, "toPandas"): + _VSCODE_df = _VSCODE_df.toPandas() # If not a known type, then just let pandas handle it. elif not (hasattr(_VSCODE_df, "iloc")): _VSCODE_df = _VSCODE_pd.DataFrame(_VSCODE_evalResult) diff --git a/src/client/datascience/interactive-common/interactiveBase.ts b/src/client/datascience/interactive-common/interactiveBase.ts index 5206e923a21f..b469af0d5f94 100644 --- a/src/client/datascience/interactive-common/interactiveBase.ts +++ b/src/client/datascience/interactive-common/interactiveBase.ts @@ -1418,7 +1418,12 @@ export abstract class InteractiveBase extends WebViewHost implements IDisposable { autoIndent: this.getValue(editor, 'autoIndent', false), fontLigatures: this.getValue(editor, 'fontLigatures', false), scrollBeyondLastLine: this.getValue(editor, 'scrollBeyondLastLine', true), - // VS Code puts a value for this, but it's 10 (the explorer bar size) not 14 the editor size + // VS Code puts a value for this, but it's 10 (the explorer bar size) not 14 the editor size for vert verticalScrollbarSize: this.getValue(editor, 'scrollbar.verticalScrollbarSize', 14), + horizontalScrollbarSize: this.getValue(editor, 'scrollbar.horizontalScrollbarSize', 10), fontSize: this.getValue(editor, 'fontSize', 14), fontFamily: this.getValue(editor, 'fontFamily', "Consolas, 'Courier New', monospace") }, @@ -346,6 +347,7 @@ export abstract class WebViewHost implements IDisposable { event.affectsConfiguration('editor.scrollBeyondLastLine') || event.affectsConfiguration('editor.fontLigatures') || event.affectsConfiguration('editor.scrollbar.verticalScrollbarSize') || + event.affectsConfiguration('editor.scrollbar.horizontalScrollbarSize') || event.affectsConfiguration('files.autoSave') || event.affectsConfiguration('files.autoSaveDelay') || event.affectsConfiguration('python.dataScience.enableGather') diff --git a/src/datascience-ui/history-react/interactivePanel.less b/src/datascience-ui/history-react/interactivePanel.less index feafd5f3f534..abab2ff7e0c1 100644 --- a/src/datascience-ui/history-react/interactivePanel.less +++ b/src/datascience-ui/history-react/interactivePanel.less @@ -1,11 +1,6 @@ /* Import common styles and then override them below */ @import "../interactive-common/common.css"; -:root { - --messages-offset-px: 20px; - --output-offset-px: 45px; -} - .toolbar-menu-bar-child { background: var(--override-background, var(--vscode-editor-background)); z-index: 10; @@ -19,7 +14,7 @@ } .messages-result-container { - width: calc(100vw - var(--messages-offset-px)); + width: 100%; } .messages-result-container pre { @@ -38,11 +33,12 @@ .cell-result-container { margin: 0px; display: grid; + grid-auto-columns: minmax(0, 1fr); } .cell-outer { display:grid; - grid-template-columns: auto 1fr 8px; + grid-template-columns: auto minmax(0, 1fr) 8px; grid-column-gap: 3px; width: 100%; } @@ -50,7 +46,7 @@ .cell-output { margin: 0px; - width: calc(100vw - var(--output-offset-px)); + width: 100%; overflow-x: scroll; background: transparent; } @@ -68,7 +64,7 @@ xmp { } .markdown-cell-output { - width: calc(100vw - var(--output-offset-px)); + width: 100%; overflow-x: scroll; } diff --git a/src/datascience-ui/history-react/interactivePanel.tsx b/src/datascience-ui/history-react/interactivePanel.tsx index 44d7e05c31a1..6b6f5abd9759 100644 --- a/src/datascience-ui/history-react/interactivePanel.tsx +++ b/src/datascience-ui/history-react/interactivePanel.tsx @@ -284,6 +284,7 @@ ${buildSettingsCss(this.props.settings)}`} testMode: this.props.testMode, codeTheme: this.props.codeTheme, submittedText: this.props.submittedText, + settings: this.props.settings, skipNextScroll: this.props.skipNextScroll ? true : false, editable: false, renderCell: this.renderCell, @@ -354,11 +355,8 @@ ${buildSettingsCss(this.props.settings)}`} this.internalScrollCount += 1; // Force auto here as smooth scrolling can be canceled by updates to the window // from elsewhere (and keeping track of these would make this hard to maintain) - // tslint:disable: no-any - if ((div as any).scrollIntoViewIfNeeded) { - (div as any).scrollIntoViewIfNeeded(false); - } else if (div && div.scrollIntoView) { - div.scrollIntoView(false); + if (div && div.scrollIntoView) { + div.scrollIntoView({ behavior: 'auto', block: 'nearest', inline: 'nearest' }); } } }; diff --git a/src/datascience-ui/history-react/redux/reducers/effects.ts b/src/datascience-ui/history-react/redux/reducers/effects.ts index 408e9547de9f..d23215ade11d 100644 --- a/src/datascience-ui/history-react/redux/reducers/effects.ts +++ b/src/datascience-ui/history-react/redux/reducers/effects.ts @@ -113,8 +113,7 @@ export namespace Effects { newVMs[index] = { ...newVMs[index], scrollCount: newVMs[index].scrollCount + 1 }; return { ...arg.prevState, - cellVMs: newVMs, - isAtBottom: false + cellVMs: newVMs }; } diff --git a/src/datascience-ui/interactive-common/buildSettingsCss.ts b/src/datascience-ui/interactive-common/buildSettingsCss.ts index 4fb67920c89f..68a2eaa0e89e 100644 --- a/src/datascience-ui/interactive-common/buildSettingsCss.ts +++ b/src/datascience-ui/interactive-common/buildSettingsCss.ts @@ -11,6 +11,14 @@ export function buildSettingsCss(settings: IDataScienceExtraSettings | undefined return settings ? `#main-panel-content::-webkit-scrollbar { width: ${settings.extraSettings.editor.verticalScrollbarSize}px; +} + +.cell-output::-webkit-scrollbar { + height: ${settings.extraSettings.editor.horizontalScrollbarSize}px; +} + +.cell-output > *::-webkit-scrollbar { + width: ${settings.extraSettings.editor.verticalScrollbarSize}px; }` : ''; } diff --git a/src/datascience-ui/interactive-common/common.css b/src/datascience-ui/interactive-common/common.css index 8ffc2b610cfe..75f7201f5563 100644 --- a/src/datascience-ui/interactive-common/common.css +++ b/src/datascience-ui/interactive-common/common.css @@ -79,7 +79,7 @@ body, html { /* Cell */ .cell-wrapper { margin: 0px; - padding: 2px; + padding: 2px 5px 2px 2px; display: block; } @@ -310,14 +310,10 @@ body, html { } #cell-table { - display: table; + display: block; width: 100%; } -#cell-table-body { - display: table-row-group; -} - .flash { animation-name: flash-animation; animation-duration: 1.0s; diff --git a/src/datascience-ui/interactive-common/contentPanel.tsx b/src/datascience-ui/interactive-common/contentPanel.tsx index 1692bd9a13a3..fba2e3ad5be3 100644 --- a/src/datascience-ui/interactive-common/contentPanel.tsx +++ b/src/datascience-ui/interactive-common/contentPanel.tsx @@ -3,6 +3,7 @@ 'use strict'; import * as React from 'react'; +import { IDataScienceExtraSettings } from '../../client/datascience/types'; import { InputHistory } from './inputHistory'; import { ICellViewModel } from './mainState'; @@ -16,6 +17,7 @@ export interface IContentPanelProps { cellVMs: ICellViewModel[]; history?: InputHistory; testMode?: boolean; + settings?: IDataScienceExtraSettings; codeTheme: string; submittedText: boolean; skipNextScroll: boolean; @@ -32,12 +34,10 @@ export class ContentPanel extends React.Component { constructor(prop: IContentPanelProps) { super(prop); } - public componentDidMount() { this.scrollToBottom(); } - - public componentDidUpdate() { + public componentWillReceiveProps() { this.scrollToBottom(); } @@ -53,12 +53,10 @@ export class ContentPanel extends React.Component { const className = `${this.props.scrollBeyondLastLine ? 'content-panel-scrollBeyondLastLine' : ''}`; return (
-
-
- {this.renderCells()} -
+
+ {this.renderCells()}
-
+
); } diff --git a/src/datascience-ui/native-editor/nativeCell.tsx b/src/datascience-ui/native-editor/nativeCell.tsx index dd45b102e4a0..dbf2db37f32d 100644 --- a/src/datascience-ui/native-editor/nativeCell.tsx +++ b/src/datascience-ui/native-editor/nativeCell.tsx @@ -44,6 +44,7 @@ interface INativeCellBaseProps { editorOptions: monacoEditor.editor.IEditorOptions; themeMatplotlibPlots: boolean | undefined; focusPending: number; + busy: boolean; } type INativeCellProps = INativeCellBaseProps & typeof actionCreators; @@ -572,6 +573,7 @@ export class NativeCell extends React.Component { onClick={runCell} tooltip={getLocString('DataScience.runCell', 'Run cell')} hidden={this.isMarkdownCell()} + disabled={this.props.busy} > @@ -629,7 +631,7 @@ export class NativeCell extends React.Component { private renderInput = () => { if (this.shouldRenderInput()) { return ( -
+
{this.renderMiddleToolbar()} { const toolbar = this.props.cellVM.cell.data.cell_type === 'markdown' ? this.renderMiddleToolbar() : null; if (this.shouldRenderOutput()) { return ( -
+
{toolbar} themeMatplotlibPlots={this.props.settings.themeMatplotlibPlots} // Focus pending does not apply to native editor. focusPending={0} + busy={this.props.busy} /> {lastLine} diff --git a/src/datascience-ui/react-common/settingsReactSide.ts b/src/datascience-ui/react-common/settingsReactSide.ts index e736dd517aa0..2aaaa5661bae 100644 --- a/src/datascience-ui/react-common/settingsReactSide.ts +++ b/src/datascience-ui/react-common/settingsReactSide.ts @@ -40,8 +40,9 @@ export function getDefaultSettings() { autoIndent: false, fontLigatures: false, scrollBeyondLastLine: true, - // VS Code puts a value for this, but it's 10 (the explorer bar size) not 14 the editor size + // VS Code puts a value for this, but it's 10 (the explorer bar size) not 14 the editor size for vert verticalScrollbarSize: 14, + horizontalScrollbarSize: 14, fontSize: 14, fontFamily: "Consolas, 'Courier New', monospace" }, diff --git a/src/test/datascience/jupyterVariables.unit.test.ts b/src/test/datascience/jupyterVariables.unit.test.ts index 11924dcb9c86..893bbba9e646 100644 --- a/src/test/datascience/jupyterVariables.unit.test.ts +++ b/src/test/datascience/jupyterVariables.unit.test.ts @@ -302,7 +302,7 @@ This is equivalent to (real + imag*1j) where imag defaults to 0. truncated: true, count: 0, shape: '', - value: '(1+1j)', + value: ' (1+1j)', supportsDataExplorer: false };