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
12 changes: 6 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
uses: actions/checkout@v2.3.4

- name: Install Node
uses: actions/setup-node@v2.1.5
uses: actions/setup-node@v2.2.0
with:
node-version: ${{env.NODE_VERSION}}

Expand Down Expand Up @@ -85,7 +85,7 @@ jobs:
uses: actions/checkout@v2.3.4

- name: Install Node
uses: actions/setup-node@v2.1.5
uses: actions/setup-node@v2.2.0
with:
node-version: ${{env.NODE_VERSION}}

Expand Down Expand Up @@ -139,7 +139,7 @@ jobs:
path: ${{env.special-working-directory-relative}}

- name: Install Node
uses: actions/setup-node@v2.1.5
uses: actions/setup-node@v2.2.0
with:
node-version: ${{env.NODE_VERSION}}

Expand All @@ -155,7 +155,7 @@ jobs:
python-version: ${{matrix.python}}

- name: Install Node
uses: actions/setup-node@v2.1.5
uses: actions/setup-node@v2.2.0
with:
node-version: ${{env.NODE_VERSION}}

Expand Down Expand Up @@ -340,7 +340,7 @@ jobs:
uses: actions/checkout@v2.3.4

- name: Install Node
uses: actions/setup-node@v2.1.5
uses: actions/setup-node@v2.2.0
with:
node-version: ${{env.NODE_VERSION}}

Expand Down Expand Up @@ -404,7 +404,7 @@ jobs:
# uses: actions/checkout@v2.3.4

# - name: Install Node
# uses: actions/setup-node@v2.1.5
# uses: actions/setup-node@v2.2.0
# with:
# node-version: ${{env.NODE_VERSION}}

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/nightly-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
uses: actions/checkout@v2.3.4

- name: Install Node
uses: actions/setup-node@v2.1.5
uses: actions/setup-node@v2.2.0
with:
node-version: ${{env.NODE_VERSION}}

Expand Down
16 changes: 8 additions & 8 deletions .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
uses: actions/checkout@v2.3.4

- name: Install Node
uses: actions/setup-node@v2.1.5
uses: actions/setup-node@v2.2.0
with:
node-version: ${{env.NODE_VERSION}}

Expand Down Expand Up @@ -60,7 +60,7 @@ jobs:
uses: actions/checkout@v2.3.4

- name: Install Node
uses: actions/setup-node@v2.1.5
uses: actions/setup-node@v2.2.0
with:
node-version: ${{env.NODE_VERSION}}

Expand Down Expand Up @@ -118,7 +118,7 @@ jobs:
path: ${{env.special-working-directory-relative}}

- name: Install Node
uses: actions/setup-node@v2.1.5
uses: actions/setup-node@v2.2.0
with:
node-version: ${{env.NODE_VERSION}}

Expand All @@ -134,7 +134,7 @@ jobs:
python-version: ${{matrix.python}}

- name: Install Node
uses: actions/setup-node@v2.1.5
uses: actions/setup-node@v2.2.0
with:
node-version: ${{env.NODE_VERSION}}

Expand Down Expand Up @@ -323,7 +323,7 @@ jobs:
uses: actions/checkout@v2.3.4

- name: Install Node
uses: actions/setup-node@v2.1.5
uses: actions/setup-node@v2.2.0
with:
node-version: ${{env.NODE_VERSION}}

Expand Down Expand Up @@ -389,7 +389,7 @@ jobs:
# uses: actions/checkout@v2.3.4

# - name: Install Node
# uses: actions/setup-node@v2.1.5
# uses: actions/setup-node@v2.2.0
# with:
# node-version: ${{env.NODE_VERSION}}

Expand Down Expand Up @@ -452,7 +452,7 @@ jobs:
uses: actions/checkout@v2.3.4

- name: Install Node
uses: actions/setup-node@v2.1.5
uses: actions/setup-node@v2.2.0
with:
node-version: ${{env.NODE_VERSION}}

Expand All @@ -468,7 +468,7 @@ jobs:
python-version: ${{env.PYTHON_VERSION}}

- name: Install Node
uses: actions/setup-node@v2.1.5
uses: actions/setup-node@v2.2.0
with:
node-version: ${{env.NODE_VERSION}}

Expand Down
1 change: 1 addition & 0 deletions news/1 Enhancements/16461.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Support starting a TensorBoard session with a remote URL hosting log files.
4 changes: 3 additions & 1 deletion package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -251,5 +251,7 @@
"TensorBoard.installProfilerPluginPrompt": "We recommend installing the PyTorch Profiler TensorBoard plugin. Would you like to install the package?",
"TensorBoard.upgradePrompt": "Integrated TensorBoard support is only available for TensorBoard >= 2.4.1. Would you like to upgrade your copy of TensorBoard?",
"TensorBoard.launchNativeTensorBoardSessionCodeAction": "Launch TensorBoard session",
"TensorBoard.launchNativeTensorBoardSessionCodeLens": "▶ Launch TensorBoard Session"
"TensorBoard.launchNativeTensorBoardSessionCodeLens": "▶ Launch TensorBoard Session",
"TensorBoard.enterRemoteUrl": "Enter remote URL",
"TensorBoard.enterRemoteUrlDetail": "Enter a URL pointing to a remote directory containing your TensorBoard log files"
}
2 changes: 1 addition & 1 deletion requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
# IntelliSense via Jedi
jedi<0.18 # For Python 2.7 support
# Sort Imports
isort==5.8.0; python_version >= '3.6'
isort==5.9.2; python_version >= '3.6'
6 changes: 3 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
#
# pip-compile --generate-hashes requirements.in
#
isort==5.8.0 ; python_version >= "3.6" \
--hash=sha256:0a943902919f65c5684ac4e0154b1ad4fac6dcaa5d9f3426b732f1c8b5419be6 \
--hash=sha256:2bb1680aad211e3c9944dbce1d4ba09a989f04e238296c87fe2139faa26d655d
isort==5.9.2 ; python_version >= "3.6" \
--hash=sha256:eed17b53c3e7912425579853d078a0832820f023191561fcee9d7cae424e0813 \
--hash=sha256:f65ce5bd4cbc6abdfbe29afc2f0245538ab358c14590912df638033f157d555e
# via -r requirements.in
jedi==0.17.2 \
--hash=sha256:86ed7d9b750603e4ba582ea8edc678657fb4007894a12bcf6f4bb97892f31d20 \
Expand Down
7 changes: 7 additions & 0 deletions src/client/common/experiments/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,10 @@ export async function inDiscoveryExperiment(experimentService: IExperimentServic
]);
return results.includes(true);
}

export function inDiscoveryExperimentSync(experimentService: IExperimentService): boolean {
return (
experimentService.inExperimentSync(DiscoveryVariants.discoverWithFileWatching) ||
experimentService.inExperimentSync(DiscoveryVariants.discoveryWithoutFileWatching)
);
}
5 changes: 5 additions & 0 deletions src/client/common/utils/localize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ export namespace Jupyter {
}

export namespace TensorBoard {
export const enterRemoteUrl = localize('TensorBoard.enterRemoteUrl', 'Enter remote URL');
export const enterRemoteUrlDetail = localize(
'TensorBoard.enterRemoteUrlDetail',
'Enter a URL pointing to a remote directory containing your TensorBoard log files',
);
export const useCurrentWorkingDirectoryDetail = localize(
'TensorBoard.useCurrentWorkingDirectoryDetail',
'TensorBoard will search for tfevent files in all subdirectories of the current working directory',
Expand Down
69 changes: 64 additions & 5 deletions src/client/interpreter/autoSelection/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@
import { inject, injectable, named } from 'inversify';
import { Event, EventEmitter, Uri } from 'vscode';
import { IWorkspaceService } from '../../common/application/types';
import { EnvironmentSorting } from '../../common/experiments/groups';
import '../../common/extensions';
import { IFileSystem } from '../../common/platform/types';
import { IPersistentState, IPersistentStateFactory, Resource } from '../../common/types';
import { IExperimentService, IPersistentState, IPersistentStateFactory, Resource } from '../../common/types';
import { createDeferred, Deferred } from '../../common/utils/async';
import { compareSemVerLikeVersions } from '../../pythonEnvironments/base/info/pythonVersion';
import { PythonEnvironment } from '../../pythonEnvironments/info';
import { captureTelemetry, sendTelemetryEvent } from '../../telemetry';
import { EventName } from '../../telemetry/constants';
import { IInterpreterHelper } from '../contracts';
import { EnvTypeHeuristic, getEnvTypeHeuristic } from '../configuration/environmentTypeComparer';
import { InterpreterComparisonType, IInterpreterComparer } from '../configuration/types';
import { IInterpreterHelper, IInterpreterService } from '../contracts';
import {
AutoSelectionRule,
IInterpreterAutoSelectionRule,
Expand Down Expand Up @@ -46,6 +49,11 @@ export class InterpreterAutoSelectionService implements IInterpreterAutoSelectio
@inject(IWorkspaceService) private readonly workspaceService: IWorkspaceService,
@inject(IPersistentStateFactory) private readonly stateFactory: IPersistentStateFactory,
@inject(IFileSystem) private readonly fs: IFileSystem,
@inject(IExperimentService) private readonly experimentService: IExperimentService,
@inject(IInterpreterService) private readonly interpreterService: IInterpreterService,
@inject(IInterpreterComparer)
@named(InterpreterComparisonType.EnvType)
private readonly envTypeComparer: IInterpreterComparer,
@inject(IInterpreterAutoSelectionRule)
@named(AutoSelectionRule.systemWide)
systemInterpreter: IInterpreterAutoSelectionRule,
Expand Down Expand Up @@ -104,19 +112,30 @@ export class InterpreterAutoSelectionService implements IInterpreterAutoSelectio
winRegInterpreter.setNextRule(systemInterpreter);
}

/**
* If there's a cached auto-selected interpreter -> return it.
* If not, check if we are in the env sorting experiment, and use the appropriate auto-selection logic.
*/
@captureTelemetry(EventName.PYTHON_INTERPRETER_AUTO_SELECTION, { rule: AutoSelectionRule.all }, true)
public async autoSelectInterpreter(resource: Resource): Promise<void> {
const key = this.getWorkspacePathKey(resource);

if (!this.autoSelectedWorkspacePromises.has(key)) {
const deferred = createDeferred<void>();
this.autoSelectedWorkspacePromises.set(key, deferred);

await this.initializeStore(resource);
await this.clearWorkspaceStoreIfInvalid(resource);
await this.userDefinedInterpreter.autoSelectInterpreter(resource, this);
this.didAutoSelectedInterpreterEmitter.fire();
Promise.all(this.rules.map((item) => item.autoSelectInterpreter(resource))).ignoreErrors();

if (await this.experimentService.inExperiment(EnvironmentSorting.experiment)) {
await this.autoselectInterpreterWithLocators(resource);
} else {
await this.autoselectInterpreterWithRules(resource);
}

deferred.resolve();
}

return this.autoSelectedWorkspacePromises.get(key)!.promise;
}

Expand Down Expand Up @@ -221,4 +240,44 @@ export class InterpreterAutoSelectionService implements IInterpreterAutoSelectio
}
return undefined;
}

private async autoselectInterpreterWithRules(resource: Resource): Promise<void> {
await this.userDefinedInterpreter.autoSelectInterpreter(resource, this);

this.didAutoSelectedInterpreterEmitter.fire();

Promise.all(this.rules.map((item) => item.autoSelectInterpreter(resource))).ignoreErrors();
}

/**
* Auto-selection logic:
* 1. If there are cached interpreters (not the first session in this workspace)
* -> sort using the same logic as in the interpreter quickpick and return the first one;
* 2. If not, we already fire all the locators, so wait for their response, sort the interpreters and return the first one.
*
* `getInterpreters` will check the cache first and return early if there are any cached interpreters,
* and if not it will wait for locators to return.
* As such, we can sort interpreters based on what it returns.
*/
private async autoselectInterpreterWithLocators(resource: Resource): Promise<void> {
const interpreters = await this.interpreterService.getInterpreters(resource);
const workspaceUri = this.interpreterHelper.getActiveWorkspaceUri(resource);

// When auto-selecting an intepreter for a workspace, we either want to return a local one
// or fallback on a globally-installed interpreter, and we don't want want to suggest a global environment
// because we would have to add a way to match environments to a workspace.
const filteredInterpreters = interpreters.filter(
(i) => getEnvTypeHeuristic(i, workspaceUri?.folderUri.fsPath || '') !== EnvTypeHeuristic.Global,
);

filteredInterpreters.sort(this.envTypeComparer.compare.bind(this.envTypeComparer));

if (workspaceUri) {
this.setWorkspaceInterpreter(workspaceUri.folderUri, filteredInterpreters[0]);
} else {
this.setGlobalInterpreter(filteredInterpreters[0]);
}

this.didAutoSelectedInterpreterEmitter.fire();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { IInterpreterComparer } from './types';
* - Global environments (pipenv, conda);
* - Globally-installed interpreters (/usr/bin/python3, Windows Store).
*/
enum EnvTypeHeuristic {
export enum EnvTypeHeuristic {
Local = 1,
Global = 2,
GlobalInterpreters = 3,
Expand Down Expand Up @@ -165,7 +165,7 @@ function compareEnvironmentType(a: PythonEnvironment, b: PythonEnvironment, work
/**
* Return a heuristic value depending on the environment type.
*/
function getEnvTypeHeuristic(environment: PythonEnvironment, workspacePath: string): EnvTypeHeuristic {
export function getEnvTypeHeuristic(environment: PythonEnvironment, workspacePath: string): EnvTypeHeuristic {
const { envType } = environment;

if (workspacePath.length > 0 && environment.envPath && isParentPath(environment.envPath, workspacePath)) {
Expand Down
4 changes: 2 additions & 2 deletions src/client/interpreter/interpreterService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
} from './contracts';
import { IVirtualEnvironmentManager } from './virtualEnvs/types';
import { getInterpreterHash } from '../pythonEnvironments/discovery/locators/services/hashProvider';
import { inDiscoveryExperiment } from '../common/experiments/helpers';
import { inDiscoveryExperiment, inDiscoveryExperimentSync } from '../common/experiments/helpers';
import { StopWatch } from '../common/utils/stopWatch';
import { PythonVersion } from '../pythonEnvironments/info/pythonVersion';

Expand Down Expand Up @@ -139,7 +139,7 @@ export class InterpreterService implements Disposable, IInterpreterService {
public async getInterpreters(resource?: Uri, options?: GetInterpreterOptions): Promise<PythonEnvironment[]> {
let environments: PythonEnvironment[] = [];
const stopWatch = new StopWatch();
if (await inDiscoveryExperiment(this.experimentService)) {
if (inDiscoveryExperimentSync(this.experimentService)) {
environments = await this.pyenvs.getInterpreters(resource, options);
} else {
const locator = this.serviceContainer.get<IInterpreterLocatorService>(
Expand Down
Loading