|
| 1 | +// Copyright (c) Microsoft Corporation. All rights reserved. |
| 2 | +// Licensed under the MIT License. |
| 3 | + |
| 4 | +import { Event, Uri } from 'vscode'; |
| 5 | +import { iterEmpty } from '../../common/utils/async'; |
| 6 | +import { PythonEnvInfo, PythonEnvKind } from './info'; |
| 7 | +import { |
| 8 | + BasicPythonEnvsChangedEvent, |
| 9 | + BasicPythonEnvsWatcher, |
| 10 | + IPythonEnvsWatcher, |
| 11 | + PythonEnvsChangedEvent, |
| 12 | + PythonEnvsWatcher |
| 13 | +} from './watcher'; |
| 14 | + |
| 15 | +/** |
| 16 | + * An async iterator of `PythonEnvInfo`. |
| 17 | + */ |
| 18 | +export type PythonEnvsIterator = AsyncIterator<PythonEnvInfo | void, void>; |
| 19 | + |
| 20 | +/** |
| 21 | + * An empty Python envs iterator. |
| 22 | + */ |
| 23 | +export const NOOP_ITERATOR: PythonEnvsIterator = iterEmpty<PythonEnvInfo>(); |
| 24 | + |
| 25 | +/** |
| 26 | + * The most basic info to send to a locator when requesting environments. |
| 27 | + * |
| 28 | + * This is directly correlated with the `BasicPythonEnvsChangedEvent` |
| 29 | + * emitted by watchers. |
| 30 | + * |
| 31 | + * @prop kinds - if provided, results should be limited to these env kinds |
| 32 | + */ |
| 33 | +export type BasicPythonLocatorQuery = { |
| 34 | + kinds?: PythonEnvKind[]; |
| 35 | +}; |
| 36 | + |
| 37 | +/** |
| 38 | + * The full set of possible info to send to a locator when requesting environments. |
| 39 | + * |
| 40 | + * This is directly correlated with the `PythonEnvsChangedEvent` |
| 41 | + * emitted by watchers. |
| 42 | + * |
| 43 | + * @prop - searchLocations - if provided, results should be limited to |
| 44 | + * within these locations |
| 45 | + */ |
| 46 | +export type PythonLocatorQuery = BasicPythonLocatorQuery & { |
| 47 | + searchLocations?: Uri[]; |
| 48 | +}; |
| 49 | + |
| 50 | +type QueryForEvent<E> = E extends PythonEnvsChangedEvent ? PythonLocatorQuery : BasicPythonLocatorQuery; |
| 51 | + |
| 52 | +/** |
| 53 | + * A single Python environment locator. |
| 54 | + * |
| 55 | + * Each locator object is responsible for identifying the Python |
| 56 | + * environments in a single location, whether a directory, a directory |
| 57 | + * tree, or otherwise. That location is identified when the locator |
| 58 | + * is instantiated. |
| 59 | + * |
| 60 | + * Based on the narrow focus of each locator, the assumption is that |
| 61 | + * calling iterEnvs() to pick up a changed env is effectively no more |
| 62 | + * expensive than tracking down that env specifically. Consequently, |
| 63 | + * events emitted via `onChanged` do not need to provide information |
| 64 | + * for the specific environments that changed. |
| 65 | + */ |
| 66 | +export interface ILocator<E extends BasicPythonEnvsChangedEvent = PythonEnvsChangedEvent> |
| 67 | + extends IPythonEnvsWatcher<E> { |
| 68 | + /** |
| 69 | + * Iterate over the enviroments known tos this locator. |
| 70 | + * |
| 71 | + * @param query - if provided, the locator will limit results to match |
| 72 | + */ |
| 73 | + iterEnvs(query?: QueryForEvent<E>): PythonEnvsIterator; |
| 74 | +} |
| 75 | + |
| 76 | +interface IBasicEmitter { |
| 77 | + fire(e: BasicPythonEnvsChangedEvent): void; |
| 78 | + trigger(kind?: PythonEnvKind): void; |
| 79 | +} |
| 80 | +interface IFullEmitter { |
| 81 | + fire(e: PythonEnvsChangedEvent): void; |
| 82 | + trigger(kind?: PythonEnvKind, searchLocation?: Uri): void; |
| 83 | +} |
| 84 | +type EmitterForEvent<E> = E extends PythonEnvsChangedEvent ? IFullEmitter : IBasicEmitter; |
| 85 | + |
| 86 | +/** |
| 87 | + * The base for locators. |
| 88 | + * |
| 89 | + * Subclasses will call `this.emitter.fire()` or `this.emitter.trigger()` |
| 90 | + * to emit events. |
| 91 | + */ |
| 92 | +abstract class Locator<E extends BasicPythonEnvsChangedEvent> { |
| 93 | + public readonly onChanged: Event<E>; |
| 94 | + protected readonly emitter: EmitterForEvent<E>; |
| 95 | + constructor(watcher: IPythonEnvsWatcher<E> & EmitterForEvent<E>) { |
| 96 | + this.emitter = watcher; |
| 97 | + this.onChanged = watcher.onChanged; |
| 98 | + } |
| 99 | + |
| 100 | + public abstract iterEnvs(query?: QueryForEvent<E>): PythonEnvsIterator; |
| 101 | +} |
| 102 | + |
| 103 | +/** |
| 104 | + * The base for locators that deal only with basic info for Python environments. |
| 105 | + * |
| 106 | + * Subclasses will call `this.emitter.fire()` or `this.emitter.trigger()` |
| 107 | + * to emit events. |
| 108 | + */ |
| 109 | +export abstract class BasicLocator extends Locator<BasicPythonEnvsChangedEvent> { |
| 110 | + constructor() { |
| 111 | + super(new BasicPythonEnvsWatcher()); |
| 112 | + } |
| 113 | +} |
| 114 | + |
| 115 | +/** |
| 116 | + * The base for locators that deal with full info for Python environments. |
| 117 | + * |
| 118 | + * Subclasses will call `this.emitter.fire()` or `this.emitter.trigger()` |
| 119 | + * to emit events. |
| 120 | + */ |
| 121 | +export abstract class FullLocator extends Locator<PythonEnvsChangedEvent> { |
| 122 | + constructor() { |
| 123 | + super(new PythonEnvsWatcher()); |
| 124 | + } |
| 125 | +} |
0 commit comments