Skip to content

Commit cfb213a

Browse files
author
Kartik Raj
committed
Ensure workspace interpreters are discovered and watched
1 parent 79e819d commit cfb213a

File tree

6 files changed

+32
-13
lines changed

6 files changed

+32
-13
lines changed

src/client/common/utils/misc.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33
'use strict';
44
import type { TextDocument, Uri } from 'vscode';
5+
import { arePathsSame, isParentPath } from '../../pythonEnvironments/common/externalDependencies';
56
import { InteractiveInputScheme, NotebookCellScheme } from '../constants';
67
import { InterpreterUri } from '../installer/types';
78
import { Resource } from '../types';
@@ -126,15 +127,15 @@ export function getURIFilter(
126127
while (candidate.path.endsWith('/')) {
127128
candidatePath = candidatePath.slice(0, -1);
128129
}
129-
if (opts.checkExact && candidatePath === uriPath) {
130+
if (opts.checkExact && arePathsSame(candidatePath, uriPath)) {
130131
return true;
131132
}
132-
if (opts.checkParent && candidatePath.startsWith(uriRoot)) {
133+
if (opts.checkParent && isParentPath(candidatePath, uriRoot)) {
133134
return true;
134135
}
135136
if (opts.checkChild) {
136-
const candidateRoot = `{candidatePath}/`;
137-
if (uriPath.startsWith(candidateRoot)) {
137+
const candidateRoot = `${candidatePath}/`;
138+
if (isParentPath(uriPath, candidateRoot)) {
138139
return true;
139140
}
140141
}

src/client/pythonEnvironments/base/locators/composite/envsCollectionCache.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
import { Event } from 'vscode';
5+
import { traceInfo } from '../../../../common/logger';
56
import { asyncFilter } from '../../../../common/utils/arrayUtils';
67
import { pathExists } from '../../../common/externalDependencies';
78
import { PythonEnvInfo } from '../../info';
@@ -112,6 +113,7 @@ export class PythonEnvInfoCache extends PythonEnvsWatcher<PythonEnvCollectionCha
112113

113114
public async flush(): Promise<void> {
114115
if (this.envs.length) {
116+
traceInfo('Environments added to cache', JSON.stringify(this.envs));
115117
await this.persistentStorage.store(this.envs);
116118
}
117119
}

src/client/pythonEnvironments/base/locators/lowLevel/fsWatchingLocator.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as fs from 'fs';
55
import * as path from 'path';
66
import { Uri } from 'vscode';
77
import { DiscoveryVariants } from '../../../../common/experiments/groups';
8+
import { traceVerbose } from '../../../../common/logger';
89
import { FileChangeType } from '../../../../common/platform/fileSystemWatcher';
910
import { sleep } from '../../../../common/utils/async';
1011
import { logError } from '../../../../logging';
@@ -33,6 +34,7 @@ function checkDirWatchable(dirname: string): DirUnwatchableReason {
3334
try {
3435
names = fs.readdirSync(dirname);
3536
} catch (err) {
37+
traceVerbose('haha', err);
3638
if (err.code === 'ENOENT') {
3739
// We treat a missing directory as watchable since it should
3840
// be watchable if created later.
@@ -42,8 +44,10 @@ function checkDirWatchable(dirname: string): DirUnwatchableReason {
4244
}
4345
// The limit here is an educated guess.
4446
if (names.length > 200) {
47+
traceVerbose('say what');
4548
return 'too many files';
4649
}
50+
traceVerbose('yep');
4751
return undefined;
4852
}
4953

@@ -92,12 +96,15 @@ export abstract class FSWatchingLocator<I = PythonEnvInfo> extends LazyResourceB
9296
// Enable global watchers only if the experiment allows it.
9397
const enableGlobalWatchers = await inExperiment(DiscoveryVariants.discoverWithFileWatching);
9498
if (!enableGlobalWatchers) {
99+
traceVerbose('Watcher disabled');
95100
return;
96101
}
97102
}
98103

99104
// Start the FS watchers.
105+
traceVerbose('Getting roots');
100106
let roots = await this.getRoots();
107+
traceVerbose('Found roots');
101108
if (typeof roots === 'string') {
102109
roots = [roots];
103110
}
@@ -106,13 +113,12 @@ export abstract class FSWatchingLocator<I = PythonEnvInfo> extends LazyResourceB
106113
// that might be watched due to a glob are not checked.
107114
const unwatchable = await checkDirWatchable(root);
108115
if (unwatchable) {
109-
logError(`dir "${root}" is not watchable (${unwatchable})`);
116+
logError(`Dir "${root}" is not watchable (${unwatchable})`);
110117
return undefined;
111118
}
112119
return root;
113120
});
114121
const watchableRoots = (await Promise.all(promises)).filter((root) => !!root) as string[];
115-
116122
watchableRoots.forEach((root) => this.startWatchers(root));
117123
}
118124

@@ -147,6 +153,7 @@ export abstract class FSWatchingLocator<I = PythonEnvInfo> extends LazyResourceB
147153
// The structure determines which globs are returned.
148154
this.opts.envStructure,
149155
);
156+
traceVerbose('Start watching root', root, 'for globs', JSON.stringify(globs));
150157
const watchers = globs.map((g) => watchLocationForPythonBinaries(root, callback, g));
151158
this.disposables.push(...watchers);
152159
}

src/client/pythonEnvironments/base/locators/lowLevel/poetryLocator.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { traceError, traceVerbose } from '../../../../common/logger';
88
import { chain, iterable } from '../../../../common/utils/async';
99
import { PythonEnvKind } from '../../info';
1010
import { BasicEnvInfo, IPythonEnvsIterator } from '../../locator';
11-
import { FSWatchingLocator } from './fsWatchingLocator';
11+
import { FSWatcherKind, FSWatchingLocator } from './fsWatchingLocator';
1212
import { getInterpreterPathFromDir } from '../../../common/commonUtils';
1313
import { pathExists } from '../../../common/externalDependencies';
1414
import { isPoetryEnvironment, localPoetryEnvDirName, Poetry } from '../../../common/environmentManagers/poetry';
@@ -65,6 +65,8 @@ export class PoetryLocator extends FSWatchingLocator<BasicEnvInfo> {
6565
super(
6666
() => getRootVirtualEnvDir(root),
6767
async () => PythonEnvKind.Poetry,
68+
undefined,
69+
FSWatcherKind.Workspace,
6870
);
6971
}
7072

src/client/pythonEnvironments/base/locators/lowLevel/workspaceVirtualEnvLocator.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { isPipenvEnvironment } from '../../../common/environmentManagers/pipenv'
1010
import { isVenvEnvironment, isVirtualenvEnvironment } from '../../../common/environmentManagers/simplevirtualenvs';
1111
import { PythonEnvKind } from '../../info';
1212
import { BasicEnvInfo, IPythonEnvsIterator } from '../../locator';
13-
import { FSWatchingLocator } from './fsWatchingLocator';
13+
import { FSWatcherKind, FSWatchingLocator } from './fsWatchingLocator';
1414
import '../../../../common/extensions';
1515
import { asyncFilter } from '../../../../common/utils/arrayUtils';
1616

@@ -52,11 +52,16 @@ async function getVirtualEnvKind(interpreterPath: string): Promise<PythonEnvKind
5252
*/
5353
export class WorkspaceVirtualEnvironmentLocator extends FSWatchingLocator<BasicEnvInfo> {
5454
public constructor(private readonly root: string) {
55-
super(() => getWorkspaceVirtualEnvDirs(this.root), getVirtualEnvKind, {
56-
// Note detecting kind of virtual env depends on the file structure around the
57-
// executable, so we need to wait before attempting to detect it.
58-
delayOnCreated: 1000,
59-
});
55+
super(
56+
() => getWorkspaceVirtualEnvDirs(this.root),
57+
getVirtualEnvKind,
58+
{
59+
// Note detecting kind of virtual env depends on the file structure around the
60+
// executable, so we need to wait before attempting to detect it.
61+
delayOnCreated: 1000,
62+
},
63+
FSWatcherKind.Workspace,
64+
);
6065
}
6166

6267
protected doIterEnvs(): IPythonEnvsIterator<BasicEnvInfo> {

src/client/pythonEnvironments/common/pythonBinariesWatcher.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import * as minimatch from 'minimatch';
77
import * as path from 'path';
8+
import { traceVerbose } from '../../common/logger';
89
import { FileChangeType, watchLocationForPattern } from '../../common/platform/fileSystemWatcher';
910
import { getOSType, OSType } from '../../common/utils/platform';
1011
import { IDisposable } from '../../common/utils/resourceLifecycle';
@@ -26,6 +27,7 @@ export function watchLocationForPythonBinaries(
2627
const resolvedGlob = path.posix.normalize(executableGlob);
2728
const [baseGlob] = resolvedGlob.split('/').slice(-1);
2829
function callbackClosure(type: FileChangeType, e: string) {
30+
traceVerbose('Received event', JSON.stringify(e), 'for baseglob', baseGlob);
2931
const isMatch = minimatch(path.basename(e), baseGlob, { nocase: getOSType() === OSType.Windows });
3032
if (!isMatch) {
3133
// When deleting the file for some reason path to all directories leading up to python are reported

0 commit comments

Comments
 (0)