diff --git a/extension/src/setup/index.ts b/extension/src/setup/index.ts index 53232c9913..b946a3fa5b 100644 --- a/extension/src/setup/index.ts +++ b/extension/src/setup/index.ts @@ -60,7 +60,11 @@ import { Title } from '../vscode/title' import { getDVCAppDir } from '../util/appdirs' import { getOptions } from '../cli/dvc/options' import { isAboveLatestTestedVersion } from '../cli/dvc/version' -import { createPythonEnv, selectPythonInterpreter } from '../extensions/python' +import { + createPythonEnv, + isActivePythonEnvGlobal, + selectPythonInterpreter +} from '../extensions/python' export class Setup extends BaseRepository @@ -396,12 +400,16 @@ export class Setup const pythonBinPath = await findPythonBinForInstall() + const isPythonEnvironmentGlobal = + isPythonExtensionUsed && (await isActivePythonEnvGlobal()) + this.webviewMessages.sendWebviewMessage({ canGitInitialize, cliCompatible: this.getCliCompatible(), dvcCliDetails, hasData, isAboveLatestTestedVersion: isAboveLatestTestedVersion(this.cliVersion), + isPythonEnvironmentGlobal, isPythonExtensionUsed, isStudioConnected: this.studioIsConnected, needsGitCommit, diff --git a/extension/src/setup/webview/contract.ts b/extension/src/setup/webview/contract.ts index 20764a6277..7a995e334e 100644 --- a/extension/src/setup/webview/contract.ts +++ b/extension/src/setup/webview/contract.ts @@ -12,6 +12,7 @@ export type SetupData = { cliCompatible: boolean | undefined dvcCliDetails: DvcCliDetails | undefined hasData: boolean | undefined + isPythonEnvironmentGlobal: boolean | undefined isPythonExtensionUsed: boolean isStudioConnected: boolean needsGitCommit: boolean diff --git a/extension/src/test/suite/setup/index.test.ts b/extension/src/test/suite/setup/index.test.ts index 0b3df59a15..add70bf636 100644 --- a/extension/src/test/suite/setup/index.test.ts +++ b/extension/src/test/suite/setup/index.test.ts @@ -356,6 +356,7 @@ suite('Setup Test Suite', () => { dvcCliDetails: { command: 'dvc', version: undefined }, hasData: false, isAboveLatestTestedVersion: undefined, + isPythonEnvironmentGlobal: false, isPythonExtensionUsed: false, isStudioConnected: false, needsGitCommit: true, @@ -400,6 +401,7 @@ suite('Setup Test Suite', () => { dvcCliDetails: { command: 'dvc', version: MIN_CLI_VERSION }, hasData: false, isAboveLatestTestedVersion: false, + isPythonEnvironmentGlobal: false, isPythonExtensionUsed: false, isStudioConnected: false, needsGitCommit: true, @@ -452,6 +454,7 @@ suite('Setup Test Suite', () => { }, hasData: false, isAboveLatestTestedVersion: false, + isPythonEnvironmentGlobal: false, isPythonExtensionUsed: false, isStudioConnected: false, needsGitCommit: false, @@ -504,6 +507,7 @@ suite('Setup Test Suite', () => { }, hasData: false, isAboveLatestTestedVersion: false, + isPythonEnvironmentGlobal: false, isPythonExtensionUsed: false, isStudioConnected: false, needsGitCommit: true, diff --git a/webview/src/setup/components/App.test.tsx b/webview/src/setup/components/App.test.tsx index 62b2c160c7..a38ecc1eb3 100644 --- a/webview/src/setup/components/App.test.tsx +++ b/webview/src/setup/components/App.test.tsx @@ -31,6 +31,7 @@ const DEFAULT_DATA = { }, hasData: false, isAboveLatestTestedVersion: false, + isPythonEnvironmentGlobal: false, isPythonExtensionUsed: false, isStudioConnected: false, needsGitCommit: false, @@ -161,7 +162,7 @@ describe('App', () => { }) const sentenceReg = new RegExp( - `DVC & DVCLive can be auto-installed with ${defaultInterpreter}.` + `Auto-install \\(pip\\) DVC & DVCLive with ${defaultInterpreter}` ) expect(screen.getByText(sentenceReg)).toBeInTheDocument() @@ -178,7 +179,7 @@ describe('App', () => { pythonBinPath: 'python' }) - const button = screen.getByText('Configure') + const button = screen.getByText('Locate DVC') fireEvent.click(button) expect(mockPostMessage).toHaveBeenCalledWith({ @@ -197,7 +198,7 @@ describe('App', () => { pythonBinPath: 'python' }) - const button = screen.getByText('Update Env') + const button = screen.getByText('Set Env') fireEvent.click(button) expect(mockPostMessage).toHaveBeenCalledWith({ @@ -223,6 +224,25 @@ describe('App', () => { }) }) + it('should let the user auto-install DVC but warn the user that their selected env is global when the Python extension is installed', () => { + const defaultInterpreter = 'python' + renderApp({ + cliCompatible: undefined, + dvcCliDetails: { + command: 'python -m dvc', + version: undefined + }, + isPythonEnvironmentGlobal: true, + isPythonExtensionUsed: true, + pythonBinPath: defaultInterpreter + }) + + const button = screen.getByText('Set Env') + + expect(button).toBeInTheDocument() + expect(screen.getByText('Not a virtual environment)')).toBeInTheDocument() + }) + it('should not show a screen saying that DVC is not installed if the cli is available', () => { renderApp() @@ -354,14 +374,14 @@ describe('App', () => { expect(within(envDetails).getByText(command)).toBeInTheDocument() }) - it('should show the user the command used to run DVC with a "Configure" button if dvc is installed without the python extension', () => { + it('should show the user the command used to run DVC with a "Locate DVC" button if dvc is installed without the python extension', () => { renderApp() const envDetails = screen.getByTestId('dvc-env-details') expect(within(envDetails).getByText('Command:')).toBeInTheDocument() - const configureButton = within(envDetails).getByText('Configure') + const configureButton = within(envDetails).getByText('Locate DVC') const selectButton = within(envDetails).queryByText( 'Select Python Interpreter' ) @@ -376,7 +396,7 @@ describe('App', () => { }) }) - it('should show the user the command used to run DVC with "Configure" and "Update Env" buttons if dvc is installed with the python extension', () => { + it('should show the user the command used to run DVC with "Locate DVC" and "Set Env" buttons if dvc is installed with the python extension', () => { renderApp({ isPythonExtensionUsed: true }) @@ -385,8 +405,8 @@ describe('App', () => { expect(within(envDetails).getByText('Command:')).toBeInTheDocument() - const configureButton = within(envDetails).getByText('Configure') - const selectButton = within(envDetails).getByText('Update Env') + const configureButton = within(envDetails).getByText('Locate DVC') + const selectButton = within(envDetails).getByText('Set Env') expect(configureButton).toBeInTheDocument() expect(selectButton).toBeInTheDocument() diff --git a/webview/src/setup/components/App.tsx b/webview/src/setup/components/App.tsx index b422eb2200..ceca06fd13 100644 --- a/webview/src/setup/components/App.tsx +++ b/webview/src/setup/components/App.tsx @@ -20,6 +20,7 @@ import { updateCliCompatible, updateDvcCliDetails, updateIsAboveLatestTestedVersion, + updateIsPythonEnvironmentGlobal, updateIsPythonExtensionUsed, updateNeedsGitInitialized, updateProjectInitialized, @@ -82,6 +83,11 @@ export const feedStore = ( case 'hasData': dispatch(updateExperimentsHasData(data.data.hasData)) continue + case 'isPythonEnvironmentGlobal': + dispatch( + updateIsPythonEnvironmentGlobal(data.data.isPythonEnvironmentGlobal) + ) + continue case 'isPythonExtensionUsed': dispatch(updateIsPythonExtensionUsed(data.data.isPythonExtensionUsed)) continue diff --git a/webview/src/setup/components/dvc/CliUnavailable.tsx b/webview/src/setup/components/dvc/CliUnavailable.tsx index d92ce8f7c8..bb90afc650 100644 --- a/webview/src/setup/components/dvc/CliUnavailable.tsx +++ b/webview/src/setup/components/dvc/CliUnavailable.tsx @@ -9,43 +9,47 @@ import { setupWorkspace, updatePythonEnvironment } from '../../util/messages' +import { Warning } from '../../../shared/components/icons' export const CliUnavailable: React.FC = ({ children }) => { - const { pythonBinPath, isPythonExtensionUsed } = useSelector( - (state: SetupState) => state.dvc - ) + const { pythonBinPath, isPythonExtensionUsed, isPythonEnvironmentGlobal } = + useSelector((state: SetupState) => state.dvc) const canInstall = !!pythonBinPath const installationSentence = ( <> The extension supports all{' '} - installation types. It can also - help to install needed packages via{' '} - pip - . + installation types. ) const conditionalContents = canInstall ? ( <>

- {installationSentence} DVC & DVCLive can be auto-installed with{' '} - {pythonBinPath}. + {installationSentence} Auto-install (pip) DVC & DVCLive with{' '} + {pythonBinPath}{' '} + {isPythonEnvironmentGlobal && ( + <> + ({' '} + Not a virtual environment) + + )} + .

) : ( <>

- {installationSentence} Unfortunately, DVC & DVCLive cannot be - auto-installed as Python was not located. + {installationSentence} DVC & DVCLive cannot be auto-installed as Python + was not located.

- {isPythonExtensionUsed && ( <> @@ -30,7 +30,7 @@ export const DvcEnvCommandRow: React.FC = ({ className={styles.buttonAsLink} onClick={updatePythonEnvironment} > - Update Env + Set Env )} diff --git a/webview/src/setup/components/dvc/styles.module.scss b/webview/src/setup/components/dvc/styles.module.scss index 971a1c2a5c..278f9dfe6c 100644 --- a/webview/src/setup/components/dvc/styles.module.scss +++ b/webview/src/setup/components/dvc/styles.module.scss @@ -32,6 +32,13 @@ } } +.inlineWarningSvg { + vertical-align: middle; + fill: $warn-color; + width: 16px; + height: 16px; +} + .buttonAsLink { @extend %buttonAsLink; diff --git a/webview/src/setup/state/dvcSlice.ts b/webview/src/setup/state/dvcSlice.ts index 0681dae4fa..11b1913795 100644 --- a/webview/src/setup/state/dvcSlice.ts +++ b/webview/src/setup/state/dvcSlice.ts @@ -15,6 +15,7 @@ export const dvcInitialState: DvcState = { cliCompatible: undefined, dvcCliDetails: undefined, isAboveLatestTestedVersion: undefined, + isPythonEnvironmentGlobal: undefined, isPythonExtensionUsed: false, needsGitInitialized: false, projectInitialized: false, @@ -47,6 +48,12 @@ export const dvcSlice = createSlice({ ) => { state.isAboveLatestTestedVersion = action.payload }, + updateIsPythonEnvironmentGlobal: ( + state, + action: PayloadAction + ) => { + state.isPythonEnvironmentGlobal = action.payload + }, updateIsPythonExtensionUsed: (state, action: PayloadAction) => { state.isPythonExtensionUsed = action.payload }, @@ -70,6 +77,7 @@ export const { updateCliCompatible, updateDvcCliDetails, updateIsAboveLatestTestedVersion, + updateIsPythonEnvironmentGlobal, updateIsPythonExtensionUsed, updateNeedsGitInitialized, updateProjectInitialized, diff --git a/webview/src/stories/Setup.stories.tsx b/webview/src/stories/Setup.stories.tsx index f36a2de201..cbf3291910 100644 --- a/webview/src/stories/Setup.stories.tsx +++ b/webview/src/stories/Setup.stories.tsx @@ -17,6 +17,7 @@ const DEFAULT_DATA: SetupData = { }, hasData: false, isAboveLatestTestedVersion: false, + isPythonEnvironmentGlobal: false, isPythonExtensionUsed: true, isStudioConnected: true, needsGitCommit: false,