profile
viewpoint

bbcmicrobit/micropython 465

Port of MicroPython for the BBC micro:bit

ericsnowcurrently/interpreters 3

Python-level access to CPython's C-level subinterpreters API.

ericsnowcurrently/AzureNotebooks 1

Repo for tracking issues and hosting samples for Azure Notebooks

ericsnowcurrently/command-center 1

A (mostly web-based) tool that consolidates all the most important stuff into a single page.

ericsnowcurrently/cpython 1

The Python programming language

ericsnowcurrently/aiohttp 0

Async http client/server framework (asyncio)

ericsnowcurrently/bedevere 0

A bot to help identify missing information for CPython pull requests

ericsnowcurrently/cherry-picker 0

🐍🍒⛏ Utility script for backporting/cherry-picking CPython changes from master into one of the maintenance branches.

ericsnowcurrently/cpython-mirror 0

Semi-official read-only mirror of the CPython Mercurial repository

ericsnowcurrently/cython 0

The most widely used Python to C compiler

push eventericsnowcurrently/vscode-python

Eric Snow

commit sha 218dd8de3ac990a3587d2cc157e6f44d18cd9dd7

Add PythonEnvInfo-related helpers. (#14051) This PR adds some basic helpers that we use in a subsequent PR. The following small drive-by changes are also included: * drop PythonEnvInfo.id property * make some internal helpers public

view details

Eric Snow

commit sha a7b8cd6b0f5e8ae31cd5be5c9faf1040313f47f6

Add a basic implementation of CachingLocator.

view details

Eric Snow

commit sha fd1c00673553962ffcf3a3fca4753eda1a294c5f

Add a noop envs cache implementation.

view details

Eric Snow

commit sha 5fabd2ad5965bfcb3e48b3ecf0dffe528199cb1d

Use CachingLocator.

view details

push time in 5 hours

push eventericsnowcurrently/vscode-python

Brett Cannon

commit sha f60eeafd3f2a86c4c10c7946b50f0a9dbd9b872d

Have dependabot ignore pytest and py (#14039) Otherwise it doesn't understand the Python 2.7 restrictions for those dependencies.

view details

Kartik Raj

commit sha 5f09a26fecc3ea784db82645a7fa6d44621c3309

Added environments reducer (#13953) * Add environments reducer * Added tests * Use path.join to construct paths * Code reviews * Correct dummy implementations and adjust tests * Modify resolveEnv() * Rename to a general parentLocator

view details

David Kutugata

commit sha fd5abc1940f2c9ae2c6365e260ab0bfdab480172

Merge release back to master (#14059) * Port ipykernel install fix to release (#13975) * Fix installing ipykernel into interpreters for raw kernel (#13959) * update news Co-authored-by: Ian Huff <ianhuff@CEIDCCEVIPSVC01.redmond.corp.microsoft.com> * Merge in changes to release (#13976) * Up release version for new release (#13928) * Up release version * Update changelog * Update changelog * Workaround test issue (#13930) * Try different version of VS code in release * Change to make it use the actual variable * Use a real version * More tests failing with gpu error (#13935) * Try different version of VS code in release * Change to make it use the actual variable * Use a real version * Two more version changes * Fix kernel and server name missing in certain situations (#13974) * Fix kernel name and server name * Fixup server name for remote situations * Add some functional tests * Add news entry * Delete news file * Port two fixes to the release branch (#13995) * Disable split views of custom editors (#13985) * Fix backup storage by looking at the options correctly (#13983) * Fix backup storage by looking at the options correctly * Fix backup by being more explicit * Only linux tests are failing. Hopefully fix them * Fixup changelog Co-authored-by: Don Jayamanne <don.jayamanne@yahoo.com> * add jedi-language-server to 3rd party notices (#13977) * add jedi-language-server to 3rd party notices * move license from distribution to repository file * disable test_discover_complex_default and (#14024) test_discover_complex_doctest * Upgrade isort to 5.5.3 (#14035) (#14037) * prepare release (#14042) * fixed annoying warnings (#14049) * update version Co-authored-by: Ian Huff <ianhu@microsoft.com> Co-authored-by: Ian Huff <ianhuff@CEIDCCEVIPSVC01.redmond.corp.microsoft.com> Co-authored-by: Rich Chiodo <rchiodo@users.noreply.github.com> Co-authored-by: Don Jayamanne <don.jayamanne@yahoo.com> Co-authored-by: Kartik Raj <karraj@microsoft.com>

view details

Karthik Nadig

commit sha e31046b212a7137a58225f398224cf9cf1a6d582

Fix object sort order in tools tests (#14050) * Fix object sort order in tools tests * rebase with main * Fix formatting

view details

Karthik Nadig

commit sha 66a4cb141b9361456a6ad23e44e249ae11a5382c

Update ubuntu images for GPU issue fix (#14064) * Update ubuntu images for GPU issue fix * Try with ubuntu-20.04

view details

Kartik Raj

commit sha 1a0c7903c0bc3c5db4a91e6bf76052604a60b614

Added environments resolver (#14019) * Modify environment info worker to support new environment type * Change worker to return interpreter information instead * Modify resolveEnv() * Code reviews * Code reviews * Move stuff

view details

Kim-Adeline Miguel

commit sha 6abde6b6f88f0b959677bf7334174ece0277986e

Add Windows unit tests to the PR pipeline (#14106)

view details

Kartik Raj

commit sha d498e8500071b2a5da65111df2592d3550220ac4

Do not opt users out of the insiders program if they have a stable version installed (#14091) * Remove code that opts users out of the insiders program * News entry * Code reviews

view details

Karthik Nadig

commit sha 12de21d5cf4ab267d3096629554b1b56f017d9c6

Do not quote isolated in exec module (#14108) * Do not quote isolated in exec module * Revert "Do not quote isolated in exec module" This reverts commit b9fa04c06be0876861017eff5ee032ca71acda3d. * Revert "IPyKernel install issue with windows paths (#13667)" This reverts commit 23725abd4249811f24475e215c2d78ed5e508e79.

view details

Don Jayamanne

commit sha 94da334bc67939a08bee24209f3e6bdecb334b98

Update cell output and metadata using Edit API (#13737)

view details

Karthik Nadig

commit sha 57fedbda5fa13bfff99d2afc29d8caa40c20cf0c

Fix unit test broken by recent revert (#14122)

view details

Karthik Nadig

commit sha d9d4265300a6d17ce91758e2a8848021baea6b3b

revert VSC_PYTHON_CI_TEST_VSC_CHANNEL changes (#14109) * revert VSC_PYTHON_CI_TEST_VSC_CHANNEL changes * Revert "revert VSC_PYTHON_CI_TEST_VSC_CHANNEL changes" This reverts commit 6ed8f61c2573d3c5030fa8398e7f25c3509d2ad5. * Remove force 1.48 on Test VSC channel

view details

Karthik Nadig

commit sha bb2ed7a7fee94dc174999996ff7aaec7c306a764

Merge environment and compare environments (#14026) * Add some heuristic functions * Support merging. * Clean up identifier code * Tweaks and fixes * More clean up. * versions tweak * Address comments * more comments * Fix merge issues. * Fix more merge issues.

view details

Eric Snow

commit sha 218dd8de3ac990a3587d2cc157e6f44d18cd9dd7

Add PythonEnvInfo-related helpers. (#14051) This PR adds some basic helpers that we use in a subsequent PR. The following small drive-by changes are also included: * drop PythonEnvInfo.id property * make some internal helpers public

view details

Eric Snow

commit sha 57e18942e3b34c19e7070c10b634cb0bd4b486e0

Lay out the source tree structure for base locator implementations.

view details

Eric Snow

commit sha 7359ab13293023237450aec3177e54e26965b0d9

Fix the module/class names for the composite locators.

view details

Eric Snow

commit sha a02f4d5acfafa5c1f36e96b7a1f4ffd8cdbc98e8

Move getInterpreterInfo() to the right file.

view details

Eric Snow

commit sha 38bb2a0ca869da456d9e61e595a0507562d242a9

Split out the getEnvInfo() tool helper.

view details

Eric Snow

commit sha 36a4f24f3596c79779a98ebb5be3a474d7a6e370

Remove the intermediary helper function.

view details

Eric Snow

commit sha 9c87aadf5d4a7a9aa5478357625b8bdce127c92f

Move files into the right place.

view details

push time in 5 hours

push eventericsnowcurrently/vscode-python

Eric Snow

commit sha 218dd8de3ac990a3587d2cc157e6f44d18cd9dd7

Add PythonEnvInfo-related helpers. (#14051) This PR adds some basic helpers that we use in a subsequent PR. The following small drive-by changes are also included: * drop PythonEnvInfo.id property * make some internal helpers public

view details

push time in 5 hours

delete branch ericsnowcurrently/vscode-python

delete branch : pyenvs-component-helpers-1

delete time in 6 hours

push eventmicrosoft/vscode-python

Eric Snow

commit sha 218dd8de3ac990a3587d2cc157e6f44d18cd9dd7

Add PythonEnvInfo-related helpers. (#14051) This PR adds some basic helpers that we use in a subsequent PR. The following small drive-by changes are also included: * drop PythonEnvInfo.id property * make some internal helpers public

view details

push time in 6 hours

PR merged microsoft/vscode-python

Add PythonEnvInfo-related helpers. skip news

This PR adds some basic helpers that we use in a subsequent PR. The following small drive-by changes are also included:

  • drop PythonEnvInfo.id property
  • make some internal helpers public

<!-- If an item below does not apply to you, then go ahead and check it off as "done" and strikethrough the text, e.g.: - [x] ~Has unit tests & system/integration tests~ -->

  • [x] Pull request represents a single change (i.e. not fixing disparate/unrelated things in a single PR).
  • [x] Title summarizes what is changing.
  • ~[ ] Has a news entry file (remember to thank yourself!).~
  • [x] Appropriate comments and documentation strings in the code.
  • ~[ ] Has sufficient logging.~
  • ~[ ] Has telemetry for enhancements.~
  • [x] Unit tests & system/integration tests are added/updated.
  • ~[ ] Test plan is updated as appropriate.~
  • ~[ ] package-lock.json has been regenerated by running npm install (if dependencies have changed).~
  • ~[ ] The wiki is updated with any design decisions/details.~
+1042 -336

2 comments

16 changed files

ericsnowcurrently

pr closed time in 6 hours

push eventericsnowcurrently/vscode-python

Eric Snow

commit sha fd5e37bd68b77556919ff944fcf1dc19d102cd7e

Add getMinimalPartialInfo().

view details

push time in 7 hours

push eventericsnowcurrently/vscode-python

Brett Cannon

commit sha f60eeafd3f2a86c4c10c7946b50f0a9dbd9b872d

Have dependabot ignore pytest and py (#14039) Otherwise it doesn't understand the Python 2.7 restrictions for those dependencies.

view details

Kartik Raj

commit sha 5f09a26fecc3ea784db82645a7fa6d44621c3309

Added environments reducer (#13953) * Add environments reducer * Added tests * Use path.join to construct paths * Code reviews * Correct dummy implementations and adjust tests * Modify resolveEnv() * Rename to a general parentLocator

view details

David Kutugata

commit sha fd5abc1940f2c9ae2c6365e260ab0bfdab480172

Merge release back to master (#14059) * Port ipykernel install fix to release (#13975) * Fix installing ipykernel into interpreters for raw kernel (#13959) * update news Co-authored-by: Ian Huff <ianhuff@CEIDCCEVIPSVC01.redmond.corp.microsoft.com> * Merge in changes to release (#13976) * Up release version for new release (#13928) * Up release version * Update changelog * Update changelog * Workaround test issue (#13930) * Try different version of VS code in release * Change to make it use the actual variable * Use a real version * More tests failing with gpu error (#13935) * Try different version of VS code in release * Change to make it use the actual variable * Use a real version * Two more version changes * Fix kernel and server name missing in certain situations (#13974) * Fix kernel name and server name * Fixup server name for remote situations * Add some functional tests * Add news entry * Delete news file * Port two fixes to the release branch (#13995) * Disable split views of custom editors (#13985) * Fix backup storage by looking at the options correctly (#13983) * Fix backup storage by looking at the options correctly * Fix backup by being more explicit * Only linux tests are failing. Hopefully fix them * Fixup changelog Co-authored-by: Don Jayamanne <don.jayamanne@yahoo.com> * add jedi-language-server to 3rd party notices (#13977) * add jedi-language-server to 3rd party notices * move license from distribution to repository file * disable test_discover_complex_default and (#14024) test_discover_complex_doctest * Upgrade isort to 5.5.3 (#14035) (#14037) * prepare release (#14042) * fixed annoying warnings (#14049) * update version Co-authored-by: Ian Huff <ianhu@microsoft.com> Co-authored-by: Ian Huff <ianhuff@CEIDCCEVIPSVC01.redmond.corp.microsoft.com> Co-authored-by: Rich Chiodo <rchiodo@users.noreply.github.com> Co-authored-by: Don Jayamanne <don.jayamanne@yahoo.com> Co-authored-by: Kartik Raj <karraj@microsoft.com>

view details

Karthik Nadig

commit sha e31046b212a7137a58225f398224cf9cf1a6d582

Fix object sort order in tools tests (#14050) * Fix object sort order in tools tests * rebase with main * Fix formatting

view details

Karthik Nadig

commit sha 66a4cb141b9361456a6ad23e44e249ae11a5382c

Update ubuntu images for GPU issue fix (#14064) * Update ubuntu images for GPU issue fix * Try with ubuntu-20.04

view details

Kartik Raj

commit sha 1a0c7903c0bc3c5db4a91e6bf76052604a60b614

Added environments resolver (#14019) * Modify environment info worker to support new environment type * Change worker to return interpreter information instead * Modify resolveEnv() * Code reviews * Code reviews * Move stuff

view details

Kim-Adeline Miguel

commit sha 6abde6b6f88f0b959677bf7334174ece0277986e

Add Windows unit tests to the PR pipeline (#14106)

view details

Kartik Raj

commit sha d498e8500071b2a5da65111df2592d3550220ac4

Do not opt users out of the insiders program if they have a stable version installed (#14091) * Remove code that opts users out of the insiders program * News entry * Code reviews

view details

Karthik Nadig

commit sha 12de21d5cf4ab267d3096629554b1b56f017d9c6

Do not quote isolated in exec module (#14108) * Do not quote isolated in exec module * Revert "Do not quote isolated in exec module" This reverts commit b9fa04c06be0876861017eff5ee032ca71acda3d. * Revert "IPyKernel install issue with windows paths (#13667)" This reverts commit 23725abd4249811f24475e215c2d78ed5e508e79.

view details

Don Jayamanne

commit sha 94da334bc67939a08bee24209f3e6bdecb334b98

Update cell output and metadata using Edit API (#13737)

view details

Karthik Nadig

commit sha 57fedbda5fa13bfff99d2afc29d8caa40c20cf0c

Fix unit test broken by recent revert (#14122)

view details

Karthik Nadig

commit sha d9d4265300a6d17ce91758e2a8848021baea6b3b

revert VSC_PYTHON_CI_TEST_VSC_CHANNEL changes (#14109) * revert VSC_PYTHON_CI_TEST_VSC_CHANNEL changes * Revert "revert VSC_PYTHON_CI_TEST_VSC_CHANNEL changes" This reverts commit 6ed8f61c2573d3c5030fa8398e7f25c3509d2ad5. * Remove force 1.48 on Test VSC channel

view details

Karthik Nadig

commit sha bb2ed7a7fee94dc174999996ff7aaec7c306a764

Merge environment and compare environments (#14026) * Add some heuristic functions * Support merging. * Clean up identifier code * Tweaks and fixes * More clean up. * versions tweak * Address comments * more comments * Fix merge issues. * Fix more merge issues.

view details

Eric Snow

commit sha 112683480d62e8fe6e5ab451ba1b8701be8ad7c7

Drop `PythonEnvInfo.id`.

view details

Eric Snow

commit sha 0d22681d8e57ab2f0364e7b2ec3f9b4f730fa34b

Make buildEmptyEnvInfo() a public helper.

view details

Eric Snow

commit sha 4468e745c2eb8a380f3805a7aa22a9a19d595889

Add a copyEnvInfo() helper.

view details

Eric Snow

commit sha 94137c8fb8a9457dbd178fa38f09e4f86f9553c3

Add locator utils.

view details

Eric Snow

commit sha eea499b53374e4c61793bcd3f0ae3dbdddf802dd

Use getEnvs() in ComponentAdapter.getInterpreters().

view details

Eric Snow

commit sha 7a2fdfc5fac0b40e8617fd5236b97965decb14b6

Add PythonEnvUpdatedEvent.index.

view details

Eric Snow

commit sha ca2ec73d8649772b0537a1d124da9d4d36850053

Fix reducer and resolver.

view details

push time in 7 hours

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

 import {  * A single update to a previously provided Python env object.  */ export type PythonEnvUpdatedEvent = {+    /**+     * The iteration index of The env info that was previously provided.+     */+    index: number;     /**      * The env info that was previously provided.-     *-     * If the event comes from `IPythonEnvsIterator.onUpdated` then-     * `old` was previously yielded during iteration.      */-    old: PythonEnvInfo;+    old?: PythonEnvInfo;

It could certainly be used for debugging. However, I can imagine it being used for other things too.

ericsnowcurrently

comment created time in 10 hours

PullRequestReviewEvent

push eventericsnowcurrently/vscode-python

Eric Snow

commit sha 1edb76def8f5a5db71610658d0c6a88d5763c75b

Strip trailing slashes in paths.

view details

push time in 10 hours

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { Uri } from 'vscode';+import { createDeferred } from '../../common/utils/async';+import { getURIFilter } from '../../common/utils/misc';+import { PythonEnvInfo } from './info';+import {+    IPythonEnvsIterator,+    PythonEnvUpdatedEvent,+    PythonLocatorQuery,+} from './locator';++/**+ * Create a filter function to match the given query.+ */+export function getQueryFilter(query: PythonLocatorQuery): (env: PythonEnvInfo) => boolean {+    const kinds = (query.kinds !== undefined && query.kinds.length > 0)+        ? query.kinds+        : undefined;+    let includeGlobal = !query.searchLocations || query.searchLocations.length === 0;+    let locationFilters: ((u: Uri) => boolean)[] | undefined;+    if (!includeGlobal) {+        const candidates = query.searchLocations!.filter((u) => !!u);+        includeGlobal = candidates.length < query.searchLocations!.length;+        if (candidates.length > 0) {+            locationFilters = candidates.map((loc) => getURIFilter(loc!, {+                checkParent: true,+                checkExact: true,

Good catch. I'll fix that.

ericsnowcurrently

comment created time in 10 hours

PullRequestReviewEvent

push eventericsnowcurrently/vscode-python

Eric Snow

commit sha f97bb3100d0ac597c88809d32d85c07bdbbbf7c4

Simplify the searchLocations logic a little.

view details

push time in 10 hours

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { Uri } from 'vscode';+import { createDeferred } from '../../common/utils/async';+import { getURIFilter } from '../../common/utils/misc';+import { PythonEnvInfo } from './info';+import {+    IPythonEnvsIterator,+    PythonEnvUpdatedEvent,+    PythonLocatorQuery,+} from './locator';++/**+ * Create a filter function to match the given query.+ */+export function getQueryFilter(query: PythonLocatorQuery): (env: PythonEnvInfo) => boolean {+    const kinds = (query.kinds !== undefined && query.kinds.length > 0)+        ? query.kinds+        : undefined;+    let includeNonRooted = true;+    if (query.searchLocations !== undefined) {+        if (query.searchLocations.includeNonRooted !== undefined) {+            includeNonRooted = query.searchLocations.includeNonRooted;+        } else {+            // We default to `false`.+            includeNonRooted = false;+        }+    }+    const locationFilters = getSearchLocationFilters(query);+    function checkKind(env: PythonEnvInfo): boolean {+        if (kinds === undefined) {+            return true;+        }+        return kinds.includes(env.kind);+    }+    function checkSearchLocation(env: PythonEnvInfo): boolean {+        if (env.searchLocation === undefined) {+            // It is not a "rooted" env.+            return includeNonRooted;+        } else {+            // It is a "rooted" env.+            if (locationFilters === undefined) {+                return query.searchLocations === undefined;+            }+            // Check against the requested roots.+            return locationFilters.some((filter) => filter(env.searchLocation!));+        }+    }+    return (env) => {+        if (!checkKind(env)) {+            return false;+        }+        if (!checkSearchLocation(env)) {+            return false;+        }+        return true;+    };+}++function getSearchLocationFilters(query: PythonLocatorQuery): ((u: Uri) => boolean)[] | undefined {+    if (query.searchLocations === undefined) {+        return undefined;+    }+    const candidates: Uri[] = query.searchLocations.roots.filter((u) => !!u);+    if (candidates.length === 0) {+        return undefined;+    }

Yeah, I don't mind doing that.

ericsnowcurrently

comment created time in 10 hours

PullRequestReviewEvent

push eventericsnowcurrently/vscode-python

Karthik Nadig

commit sha d9d4265300a6d17ce91758e2a8848021baea6b3b

revert VSC_PYTHON_CI_TEST_VSC_CHANNEL changes (#14109) * revert VSC_PYTHON_CI_TEST_VSC_CHANNEL changes * Revert "revert VSC_PYTHON_CI_TEST_VSC_CHANNEL changes" This reverts commit 6ed8f61c2573d3c5030fa8398e7f25c3509d2ad5. * Remove force 1.48 on Test VSC channel

view details

Karthik Nadig

commit sha bb2ed7a7fee94dc174999996ff7aaec7c306a764

Merge environment and compare environments (#14026) * Add some heuristic functions * Support merging. * Clean up identifier code * Tweaks and fixes * More clean up. * versions tweak * Address comments * more comments * Fix merge issues. * Fix more merge issues.

view details

Eric Snow

commit sha 112683480d62e8fe6e5ab451ba1b8701be8ad7c7

Drop `PythonEnvInfo.id`.

view details

Eric Snow

commit sha 0d22681d8e57ab2f0364e7b2ec3f9b4f730fa34b

Make buildEmptyEnvInfo() a public helper.

view details

Eric Snow

commit sha 4468e745c2eb8a380f3805a7aa22a9a19d595889

Add a copyEnvInfo() helper.

view details

Eric Snow

commit sha 94137c8fb8a9457dbd178fa38f09e4f86f9553c3

Add locator utils.

view details

Eric Snow

commit sha eea499b53374e4c61793bcd3f0ae3dbdddf802dd

Use getEnvs() in ComponentAdapter.getInterpreters().

view details

Eric Snow

commit sha 7a2fdfc5fac0b40e8617fd5236b97965decb14b6

Add PythonEnvUpdatedEvent.index.

view details

Eric Snow

commit sha ca2ec73d8649772b0537a1d124da9d4d36850053

Fix reducer and resolver.

view details

Eric Snow

commit sha af6c7c5e2270d41ef3b09c508cab17072239ed6a

Make parseVersion() a public helper.

view details

Eric Snow

commit sha e737607f71312908defec41c65cac4b96aa5650b

buildEmptyEnvInfo() -> buildEnvInfo().

view details

Eric Snow

commit sha 51c6dee565043d823285b004283dfcb57e55a542

Factor out updateEnv().

view details

Eric Snow

commit sha 2ecd537309ab5bad9efdf8e21374aa27f92e2d1d

Use lodash.cloneDeep() to deep-copy objects.

view details

Eric Snow

commit sha 9cd6c7dde332bf82ce92cb657481faa8e805f863

Drop the testing helper createEnv().

view details

Eric Snow

commit sha 6b509730e36ca866aea05f72197a2515d912df7b

Factor out getURIFilter().

view details

Eric Snow

commit sha ad8f195ac9384f9c2d69a0def5e295625e6c4825

Allow locator queries to mix search locations and non.

view details

Eric Snow

commit sha 2b70a1c86bb40fbe0c27552b55bf2b4c22ace445

Match subdirectories in locator queries.

view details

Eric Snow

commit sha 7b1953880205e8e6d72d440291c7d67df63dc670

Make PythonVersion.release optional.

view details

Eric Snow

commit sha eb746f94795e48fb927005fd440cfa5559ad3c36

Drop the fixPath() testing helper.

view details

Eric Snow

commit sha 20c46daceae752dcd121ef6e5d84446b170e4ab6

lint

view details

push time in 10 hours

push eventericsnowcurrently/vscode-python

Karthik Nadig

commit sha d9d4265300a6d17ce91758e2a8848021baea6b3b

revert VSC_PYTHON_CI_TEST_VSC_CHANNEL changes (#14109) * revert VSC_PYTHON_CI_TEST_VSC_CHANNEL changes * Revert "revert VSC_PYTHON_CI_TEST_VSC_CHANNEL changes" This reverts commit 6ed8f61c2573d3c5030fa8398e7f25c3509d2ad5. * Remove force 1.48 on Test VSC channel

view details

Karthik Nadig

commit sha bb2ed7a7fee94dc174999996ff7aaec7c306a764

Merge environment and compare environments (#14026) * Add some heuristic functions * Support merging. * Clean up identifier code * Tweaks and fixes * More clean up. * versions tweak * Address comments * more comments * Fix merge issues. * Fix more merge issues.

view details

push time in 11 hours

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { Uri } from 'vscode';+import { createDeferred } from '../../common/utils/async';+import { getURIFilter } from '../../common/utils/misc';+import { PythonEnvInfo } from './info';+import {+    IPythonEnvsIterator,+    PythonEnvUpdatedEvent,+    PythonLocatorQuery,+} from './locator';++/**+ * Create a filter function to match the given query.+ */+export function getQueryFilter(query: PythonLocatorQuery): (env: PythonEnvInfo) => boolean {+    const kinds = (query.kinds !== undefined && query.kinds.length > 0)+        ? query.kinds+        : undefined;+    let includeNonRooted = true;+    if (query.searchLocations !== undefined) {+        if (query.searchLocations.includeNonRooted !== undefined) {+            includeNonRooted = query.searchLocations.includeNonRooted;+        } else {+            // We default to `false`.+            includeNonRooted = false;+        }+    }+    const locationFilters = getSearchLocationFilters(query);+    function checkKind(env: PythonEnvInfo): boolean {+        if (kinds === undefined) {+            return true;+        }+        return kinds.includes(env.kind);+    }+    function checkSearchLocation(env: PythonEnvInfo): boolean {+        if (env.searchLocation === undefined) {+            // It is not a "rooted" env.+            return includeNonRooted;+        } else {+            // It is a "rooted" env.+            if (locationFilters === undefined) {+                return query.searchLocations === undefined;+            }+            // Check against the requested roots.+            return locationFilters.some((filter) => filter(env.searchLocation!));+        }+    }+    return (env) => {+        if (!checkKind(env)) {+            return false;+        }+        if (!checkSearchLocation(env)) {+            return false;+        }+        return true;+    };+}++function getSearchLocationFilters(query: PythonLocatorQuery): ((u: Uri) => boolean)[] | undefined {+    if (query.searchLocations === undefined) {+        return undefined;+    }+    const candidates: Uri[] = query.searchLocations.roots.filter((u) => !!u);

I found the problem (in a test), so I've dropped that filtering.

ericsnowcurrently

comment created time in 11 hours

PullRequestReviewEvent

push eventericsnowcurrently/vscode-python

Eric Snow

commit sha 9d9acdf1dd0c55ad4120cf732d9dcd809aa11385

Filter out undefined locations in the tests.

view details

push time in 11 hours

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { Uri } from 'vscode';+import { createDeferred } from '../../common/utils/async';+import { getURIFilter } from '../../common/utils/misc';+import { PythonEnvInfo } from './info';+import {+    IPythonEnvsIterator,+    PythonEnvUpdatedEvent,+    PythonLocatorQuery,+} from './locator';++/**+ * Create a filter function to match the given query.+ */+export function getQueryFilter(query: PythonLocatorQuery): (env: PythonEnvInfo) => boolean {+    const kinds = (query.kinds !== undefined && query.kinds.length > 0)+        ? query.kinds+        : undefined;+    let includeNonRooted = true;+    if (query.searchLocations !== undefined) {+        if (query.searchLocations.includeNonRooted !== undefined) {+            includeNonRooted = query.searchLocations.includeNonRooted;+        } else {+            // We default to `false`.+            includeNonRooted = false;+        }+    }+    const locationFilters = getSearchLocationFilters(query);+    function checkKind(env: PythonEnvInfo): boolean {+        if (kinds === undefined) {+            return true;+        }+        return kinds.includes(env.kind);+    }+    function checkSearchLocation(env: PythonEnvInfo): boolean {+        if (env.searchLocation === undefined) {+            // It is not a "rooted" env.+            return includeNonRooted;+        } else {+            // It is a "rooted" env.+            if (locationFilters === undefined) {+                return query.searchLocations === undefined;+            }+            // Check against the requested roots.+            return locationFilters.some((filter) => filter(env.searchLocation!));+        }+    }+    return (env) => {+        if (!checkKind(env)) {+            return false;+        }+        if (!checkSearchLocation(env)) {+            return false;+        }+        return true;+    };+}++function getSearchLocationFilters(query: PythonLocatorQuery): ((u: Uri) => boolean)[] | undefined {+    if (query.searchLocations === undefined) {+        return undefined;+    }+    const candidates: Uri[] = query.searchLocations.roots.filter((u) => !!u);

I'd say "no" except for whatever reason I ran into a case where I was getting undefined values. Perhaps that is no longer the case. I'll double check.

ericsnowcurrently

comment created time in 11 hours

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { Uri } from 'vscode';+import { createDeferred } from '../../common/utils/async';+import { getURIFilter } from '../../common/utils/misc';+import { PythonEnvInfo } from './info';+import {+    IPythonEnvsIterator,+    PythonEnvUpdatedEvent,+    PythonLocatorQuery,+} from './locator';++/**+ * Create a filter function to match the given query.+ */+export function getQueryFilter(query: PythonLocatorQuery): (env: PythonEnvInfo) => boolean {+    const kinds = (query.kinds !== undefined && query.kinds.length > 0)+        ? query.kinds+        : undefined;+    let includeNonRooted = true;+    if (query.searchLocations !== undefined) {+        if (query.searchLocations.includeNonRooted !== undefined) {+            includeNonRooted = query.searchLocations.includeNonRooted;+        } else {+            // We default to `false`.+            includeNonRooted = false;+        }+    }+    const locationFilters = getSearchLocationFilters(query);+    function checkKind(env: PythonEnvInfo): boolean {+        if (kinds === undefined) {+            return true;+        }+        return kinds.includes(env.kind);+    }+    function checkSearchLocation(env: PythonEnvInfo): boolean {+        if (env.searchLocation === undefined) {+            // It is not a "rooted" env.+            return includeNonRooted;+        } else {+            // It is a "rooted" env.+            if (locationFilters === undefined) {+                return query.searchLocations === undefined;+            }+            // Check against the requested roots.+            return locationFilters.some((filter) => filter(env.searchLocation!));+        }+    }+    return (env) => {+        if (!checkKind(env)) {+            return false;+        }+        if (!checkSearchLocation(env)) {+            return false;+        }+        return true;

I want to draw attention to the fact that each of these is a distinct operation. Folding them into one line obscures that. Otherwise I'd agree. 😄

ericsnowcurrently

comment created time in 11 hours

PullRequestReviewEvent

push eventericsnowcurrently/vscode-python

Eric Snow

commit sha 3359a2effff6b80e97f566d02b60342351b50a12

Fix a sonarcloud warning.

view details

push time in 11 hours

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { Architecture } from '../../../common/utils/platform';++import {+    PythonEnvInfo,+    PythonEnvKind,+    PythonReleaseLevel,+    PythonVersion,+} from '.';++/**+ * Create a new info object with all values empty.+ *+ * @param init - if provided, these values are applied to the new object+ */+export function buildEnvInfo(init?: {+    kind?: PythonEnvKind;+    executable?: string;

It's a convenience function for the common cases. If the caller has a more complex value to use then they can set it on the returned object.

ericsnowcurrently

comment created time in 12 hours

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { Uri } from 'vscode';+import { createDeferred } from '../../common/utils/async';+import { getURIFilter } from '../../common/utils/misc';+import { PythonEnvInfo } from './info';+import {+    IPythonEnvsIterator,+    PythonEnvUpdatedEvent,+    PythonLocatorQuery,+} from './locator';++/**+ * Create a filter function to match the given query.+ */+export function getQueryFilter(query: PythonLocatorQuery): (env: PythonEnvInfo) => boolean {+    const kinds = (query.kinds !== undefined && query.kinds.length > 0)+        ? query.kinds+        : undefined;+    let includeGlobal = !query.searchLocations || query.searchLocations.length === 0;

This code has been refactored.

ericsnowcurrently

comment created time in 12 hours

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { Uri } from 'vscode';+import { createDeferred } from '../../common/utils/async';+import { getURIFilter } from '../../common/utils/misc';+import { PythonEnvInfo } from './info';+import {+    IPythonEnvsIterator,+    PythonEnvUpdatedEvent,+    PythonLocatorQuery,+} from './locator';++/**+ * Create a filter function to match the given query.+ */+export function getQueryFilter(query: PythonLocatorQuery): (env: PythonEnvInfo) => boolean {+    const kinds = (query.kinds !== undefined && query.kinds.length > 0)+        ? query.kinds+        : undefined;+    let includeGlobal = !query.searchLocations || query.searchLocations.length === 0;+    let locationFilters: ((u: Uri) => boolean)[] | undefined;+    if (!includeGlobal) {+        const candidates = query.searchLocations!.filter((u) => !!u);+        includeGlobal = candidates.length < query.searchLocations!.length;+        if (candidates.length > 0) {+            locationFilters = candidates.map((loc) => getURIFilter(loc!, {+                checkParent: true,+                checkExact: true,

Note that uriRoot is not uri.path. Instead it has a trailing slash. So the two cases are mutually exclusive.

ericsnowcurrently

comment created time in 12 hours

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { Uri } from 'vscode';+import { createDeferred } from '../../common/utils/async';+import { getURIFilter } from '../../common/utils/misc';+import { PythonEnvInfo } from './info';+import {+    IPythonEnvsIterator,+    PythonEnvUpdatedEvent,+    PythonLocatorQuery,+} from './locator';++/**+ * Create a filter function to match the given query.+ */+export function getQueryFilter(query: PythonLocatorQuery): (env: PythonEnvInfo) => boolean {+    const kinds = (query.kinds !== undefined && query.kinds.length > 0)+        ? query.kinds+        : undefined;+    let includeGlobal = !query.searchLocations || query.searchLocations.length === 0;+    let locationFilters: ((u: Uri) => boolean)[] | undefined;+    if (!includeGlobal) {+        const candidates = query.searchLocations!.filter((u) => !!u);

It's just typescript not being smart enough. Regardless, I've mostly cleaned this up.

ericsnowcurrently

comment created time in 12 hours

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

 export type BasicPythonLocatorQuery = {  * emitted by watchers.  *  * @prop - searchLocations - if provided, results should be limited to- *         within these locations+ *         within these locations; `null` means "include envs that have+ *         no search location"  */ export type PythonLocatorQuery = BasicPythonLocatorQuery & {-    searchLocations?: Uri[];+    searchLocations?: (Uri | null)[] | null;

What about when searchLocations is not defined, does it mean return all environments regardless of location?

Yeah, it means ignore env.searchLocation. I've clarified that in the doc comment.

ericsnowcurrently

comment created time in 12 hours

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

 export type BasicPythonLocatorQuery = {  * emitted by watchers.  *  * @prop - searchLocations - if provided, results should be limited to- *         within these locations+ *         within these locations; `null` means "include envs that have+ *         no search location"  */ export type PythonLocatorQuery = BasicPythonLocatorQuery & {-    searchLocations?: Uri[];+    searchLocations?: (Uri | null)[] | null;

fixed

ericsnowcurrently

comment created time in 12 hours

PullRequestReviewEvent

push eventericsnowcurrently/vscode-python

Brett Cannon

commit sha f60eeafd3f2a86c4c10c7946b50f0a9dbd9b872d

Have dependabot ignore pytest and py (#14039) Otherwise it doesn't understand the Python 2.7 restrictions for those dependencies.

view details

Kartik Raj

commit sha 5f09a26fecc3ea784db82645a7fa6d44621c3309

Added environments reducer (#13953) * Add environments reducer * Added tests * Use path.join to construct paths * Code reviews * Correct dummy implementations and adjust tests * Modify resolveEnv() * Rename to a general parentLocator

view details

David Kutugata

commit sha fd5abc1940f2c9ae2c6365e260ab0bfdab480172

Merge release back to master (#14059) * Port ipykernel install fix to release (#13975) * Fix installing ipykernel into interpreters for raw kernel (#13959) * update news Co-authored-by: Ian Huff <ianhuff@CEIDCCEVIPSVC01.redmond.corp.microsoft.com> * Merge in changes to release (#13976) * Up release version for new release (#13928) * Up release version * Update changelog * Update changelog * Workaround test issue (#13930) * Try different version of VS code in release * Change to make it use the actual variable * Use a real version * More tests failing with gpu error (#13935) * Try different version of VS code in release * Change to make it use the actual variable * Use a real version * Two more version changes * Fix kernel and server name missing in certain situations (#13974) * Fix kernel name and server name * Fixup server name for remote situations * Add some functional tests * Add news entry * Delete news file * Port two fixes to the release branch (#13995) * Disable split views of custom editors (#13985) * Fix backup storage by looking at the options correctly (#13983) * Fix backup storage by looking at the options correctly * Fix backup by being more explicit * Only linux tests are failing. Hopefully fix them * Fixup changelog Co-authored-by: Don Jayamanne <don.jayamanne@yahoo.com> * add jedi-language-server to 3rd party notices (#13977) * add jedi-language-server to 3rd party notices * move license from distribution to repository file * disable test_discover_complex_default and (#14024) test_discover_complex_doctest * Upgrade isort to 5.5.3 (#14035) (#14037) * prepare release (#14042) * fixed annoying warnings (#14049) * update version Co-authored-by: Ian Huff <ianhu@microsoft.com> Co-authored-by: Ian Huff <ianhuff@CEIDCCEVIPSVC01.redmond.corp.microsoft.com> Co-authored-by: Rich Chiodo <rchiodo@users.noreply.github.com> Co-authored-by: Don Jayamanne <don.jayamanne@yahoo.com> Co-authored-by: Kartik Raj <karraj@microsoft.com>

view details

Karthik Nadig

commit sha e31046b212a7137a58225f398224cf9cf1a6d582

Fix object sort order in tools tests (#14050) * Fix object sort order in tools tests * rebase with main * Fix formatting

view details

Karthik Nadig

commit sha 66a4cb141b9361456a6ad23e44e249ae11a5382c

Update ubuntu images for GPU issue fix (#14064) * Update ubuntu images for GPU issue fix * Try with ubuntu-20.04

view details

Kartik Raj

commit sha 1a0c7903c0bc3c5db4a91e6bf76052604a60b614

Added environments resolver (#14019) * Modify environment info worker to support new environment type * Change worker to return interpreter information instead * Modify resolveEnv() * Code reviews * Code reviews * Move stuff

view details

Kim-Adeline Miguel

commit sha 6abde6b6f88f0b959677bf7334174ece0277986e

Add Windows unit tests to the PR pipeline (#14106)

view details

Kartik Raj

commit sha d498e8500071b2a5da65111df2592d3550220ac4

Do not opt users out of the insiders program if they have a stable version installed (#14091) * Remove code that opts users out of the insiders program * News entry * Code reviews

view details

Karthik Nadig

commit sha 12de21d5cf4ab267d3096629554b1b56f017d9c6

Do not quote isolated in exec module (#14108) * Do not quote isolated in exec module * Revert "Do not quote isolated in exec module" This reverts commit b9fa04c06be0876861017eff5ee032ca71acda3d. * Revert "IPyKernel install issue with windows paths (#13667)" This reverts commit 23725abd4249811f24475e215c2d78ed5e508e79.

view details

Don Jayamanne

commit sha 94da334bc67939a08bee24209f3e6bdecb334b98

Update cell output and metadata using Edit API (#13737)

view details

Karthik Nadig

commit sha 57fedbda5fa13bfff99d2afc29d8caa40c20cf0c

Fix unit test broken by recent revert (#14122)

view details

Eric Snow

commit sha bd4483283b922505cc2a5c2b55dc7c40b8b6aaab

Drop `PythonEnvInfo.id`.

view details

Eric Snow

commit sha f966d75d9d365a61ad910ee8bede6a0740fc7671

Add placeholder env info utils.

view details

Eric Snow

commit sha a8c7e3527236bc66d444b7d7fb2051673057c027

Make buildEmptyEnvInfo() a public helper.

view details

Eric Snow

commit sha 440dc9f32f8aac3c81b50f7b5acbe5d71c6f9f60

Add a copyEnvInfo() helper.

view details

Eric Snow

commit sha dc274036c5fe0de7c98f381c5cae73c3a1a77a7f

Add locator utils.

view details

Eric Snow

commit sha e308396264e104204f55d8fc0e9dccefe45de4ba

Use getEnvs() in ComponentAdapter.getInterpreters().

view details

Eric Snow

commit sha 4356247b7b67acc0fe270f08f8c7d98159595fe6

Add PythonEnvUpdatedEvent.index.

view details

Eric Snow

commit sha d3a1464d2c74da20e61f00a11daeaeb57460d1b5

Drop the placeholder info utils.

view details

Eric Snow

commit sha 9ed0cb336d18c7fba3a2d4cf1d1df79bcae296ed

Make parseVersion() a public helper.

view details

push time in 12 hours

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

 export type BasicPythonLocatorQuery = {  * emitted by watchers.  *  * @prop - searchLocations - if provided, results should be limited to- *         within these locations+ *         within these locations; `null` means "include envs that have+ *         no search location"  */ export type PythonLocatorQuery = BasicPythonLocatorQuery & {-    searchLocations?: Uri[];+    searchLocations?: (Uri | null)[] | null;

I'm going to make that change regardless. 😄

ericsnowcurrently

comment created time in 14 hours

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { Uri } from 'vscode';+import { createDeferred } from '../../common/utils/async';+import { getURIFilter } from '../../common/utils/misc';+import { PythonEnvInfo } from './info';+import {+    IPythonEnvsIterator,+    PythonEnvUpdatedEvent,+    PythonLocatorQuery,+} from './locator';++/**+ * Create a filter function to match the given query.+ */+export function getQueryFilter(query: PythonLocatorQuery): (env: PythonEnvInfo) => boolean {+    const kinds = (query.kinds !== undefined && query.kinds.length > 0)+        ? query.kinds+        : undefined;+    let includeGlobal = !query.searchLocations || query.searchLocations.length === 0;

It is covered by !query.searchLocations.

ericsnowcurrently

comment created time in 14 hours

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { Uri } from 'vscode';+import { createDeferred } from '../../common/utils/async';+import { getURIFilter } from '../../common/utils/misc';+import { PythonEnvInfo } from './info';+import {+    IPythonEnvsIterator,+    PythonEnvUpdatedEvent,+    PythonLocatorQuery,+} from './locator';++/**+ * Create a filter function to match the given query.+ */+export function getQueryFilter(query: PythonLocatorQuery): (env: PythonEnvInfo) => boolean {+    const kinds = (query.kinds !== undefined && query.kinds.length > 0)+        ? query.kinds+        : undefined;+    let includeGlobal = !query.searchLocations || query.searchLocations.length === 0;+    let locationFilters: ((u: Uri) => boolean)[] | undefined;+    if (!includeGlobal) {+        const candidates = query.searchLocations!.filter((u) => !!u);+        includeGlobal = candidates.length < query.searchLocations!.length;+        if (candidates.length > 0) {+            locationFilters = candidates.map((loc) => getURIFilter(loc!, {+                checkParent: true,+                checkExact: true,+            }));+        }+    }+    function checkKind(env: PythonEnvInfo): boolean {+        if (kinds === undefined) {+            return true;+        }+        return kinds.includes(env.kind);+    }+    function checkSearchLocation(env: PythonEnvInfo): boolean {+        if (env.searchLocation === undefined) {+            // It is not a "rooted" env.+            return includeGlobal;+        }++        // It is a "rooted" env.+        if (locationFilters === undefined) {

It means what the comment says. Also see https://github.com/microsoft/vscode-python/pull/14051#discussion_r496110059.

ericsnowcurrently

comment created time in 14 hours

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { Uri } from 'vscode';+import { createDeferred } from '../../common/utils/async';+import { getURIFilter } from '../../common/utils/misc';+import { PythonEnvInfo } from './info';+import {+    IPythonEnvsIterator,+    PythonEnvUpdatedEvent,+    PythonLocatorQuery,+} from './locator';++/**+ * Create a filter function to match the given query.+ */+export function getQueryFilter(query: PythonLocatorQuery): (env: PythonEnvInfo) => boolean {+    const kinds = (query.kinds !== undefined && query.kinds.length > 0)+        ? query.kinds+        : undefined;+    let includeGlobal = !query.searchLocations || query.searchLocations.length === 0;+    let locationFilters: ((u: Uri) => boolean)[] | undefined;+    if (!includeGlobal) {+        const candidates = query.searchLocations!.filter((u) => !!u);+        includeGlobal = candidates.length < query.searchLocations!.length;+        if (candidates.length > 0) {+            locationFilters = candidates.map((loc) => getURIFilter(loc!, {+                checkParent: true,+                checkExact: true,

checkParent and checkExact are supposed to be mutually exclusive. If they are not then it is a bug.

ericsnowcurrently

comment created time in 14 hours

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Add PythonEnvInfo-related helpers.

 export type BasicPythonLocatorQuery = {  * emitted by watchers.  *  * @prop - searchLocations - if provided, results should be limited to- *         within these locations+ *         within these locations; `null` means "include envs that have+ *         no search location"  */ export type PythonLocatorQuery = BasicPythonLocatorQuery & {-    searchLocations?: Uri[];+    searchLocations?: (Uri | null)[] | null;

Here are the meanings:

  • null - "ignore envs with a search location"
  • Uri[] - "include all searched envs that match these locations, along with all non-searched envs"
  • (Uri | null)[] - "include only envs that match these search locations"

It may be simpler to make PythonLocatorQuery.searchLocations be an object:

    searchLocations?: {
        roots: Uri[];
        includeNonRooted: boolean;
    };

Would that help clarify things?

ericsnowcurrently

comment created time in 14 hours

PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Merge environment and compare environments

+// Copyright (c) Microsoft Corporation. All rights reserved.++import { PythonVersion } from '.';++// Licensed under the MIT License.+export function areSameVersion(left: PythonVersion, right:PythonVersion): boolean {

What do you mean by "different object"? The module I mentioned currently only has parseVersion() in it and that function deals with PythonVersion (the same as areSameVersion()). I'd expect all helpers related to PythonVersion to be in the same module.

karthiknadig

comment created time in 15 hours

push eventericsnowcurrently/vscode-python

Brett Cannon

commit sha f60eeafd3f2a86c4c10c7946b50f0a9dbd9b872d

Have dependabot ignore pytest and py (#14039) Otherwise it doesn't understand the Python 2.7 restrictions for those dependencies.

view details

Kartik Raj

commit sha 5f09a26fecc3ea784db82645a7fa6d44621c3309

Added environments reducer (#13953) * Add environments reducer * Added tests * Use path.join to construct paths * Code reviews * Correct dummy implementations and adjust tests * Modify resolveEnv() * Rename to a general parentLocator

view details

David Kutugata

commit sha fd5abc1940f2c9ae2c6365e260ab0bfdab480172

Merge release back to master (#14059) * Port ipykernel install fix to release (#13975) * Fix installing ipykernel into interpreters for raw kernel (#13959) * update news Co-authored-by: Ian Huff <ianhuff@CEIDCCEVIPSVC01.redmond.corp.microsoft.com> * Merge in changes to release (#13976) * Up release version for new release (#13928) * Up release version * Update changelog * Update changelog * Workaround test issue (#13930) * Try different version of VS code in release * Change to make it use the actual variable * Use a real version * More tests failing with gpu error (#13935) * Try different version of VS code in release * Change to make it use the actual variable * Use a real version * Two more version changes * Fix kernel and server name missing in certain situations (#13974) * Fix kernel name and server name * Fixup server name for remote situations * Add some functional tests * Add news entry * Delete news file * Port two fixes to the release branch (#13995) * Disable split views of custom editors (#13985) * Fix backup storage by looking at the options correctly (#13983) * Fix backup storage by looking at the options correctly * Fix backup by being more explicit * Only linux tests are failing. Hopefully fix them * Fixup changelog Co-authored-by: Don Jayamanne <don.jayamanne@yahoo.com> * add jedi-language-server to 3rd party notices (#13977) * add jedi-language-server to 3rd party notices * move license from distribution to repository file * disable test_discover_complex_default and (#14024) test_discover_complex_doctest * Upgrade isort to 5.5.3 (#14035) (#14037) * prepare release (#14042) * fixed annoying warnings (#14049) * update version Co-authored-by: Ian Huff <ianhu@microsoft.com> Co-authored-by: Ian Huff <ianhuff@CEIDCCEVIPSVC01.redmond.corp.microsoft.com> Co-authored-by: Rich Chiodo <rchiodo@users.noreply.github.com> Co-authored-by: Don Jayamanne <don.jayamanne@yahoo.com> Co-authored-by: Kartik Raj <karraj@microsoft.com>

view details

Karthik Nadig

commit sha e31046b212a7137a58225f398224cf9cf1a6d582

Fix object sort order in tools tests (#14050) * Fix object sort order in tools tests * rebase with main * Fix formatting

view details

Karthik Nadig

commit sha 66a4cb141b9361456a6ad23e44e249ae11a5382c

Update ubuntu images for GPU issue fix (#14064) * Update ubuntu images for GPU issue fix * Try with ubuntu-20.04

view details

Kartik Raj

commit sha 1a0c7903c0bc3c5db4a91e6bf76052604a60b614

Added environments resolver (#14019) * Modify environment info worker to support new environment type * Change worker to return interpreter information instead * Modify resolveEnv() * Code reviews * Code reviews * Move stuff

view details

Kim-Adeline Miguel

commit sha 6abde6b6f88f0b959677bf7334174ece0277986e

Add Windows unit tests to the PR pipeline (#14106)

view details

Kartik Raj

commit sha d498e8500071b2a5da65111df2592d3550220ac4

Do not opt users out of the insiders program if they have a stable version installed (#14091) * Remove code that opts users out of the insiders program * News entry * Code reviews

view details

Karthik Nadig

commit sha 12de21d5cf4ab267d3096629554b1b56f017d9c6

Do not quote isolated in exec module (#14108) * Do not quote isolated in exec module * Revert "Do not quote isolated in exec module" This reverts commit b9fa04c06be0876861017eff5ee032ca71acda3d. * Revert "IPyKernel install issue with windows paths (#13667)" This reverts commit 23725abd4249811f24475e215c2d78ed5e508e79.

view details

Don Jayamanne

commit sha 94da334bc67939a08bee24209f3e6bdecb334b98

Update cell output and metadata using Edit API (#13737)

view details

Karthik Nadig

commit sha 57fedbda5fa13bfff99d2afc29d8caa40c20cf0c

Fix unit test broken by recent revert (#14122)

view details

push time in 15 hours

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {+    private envsList: PythonEnvInfo[] | undefined;++    private persistentStorage: IPersistentState<PythonEnvInfo[]> | undefined;++    constructor(private readonly isComplete: CompleteEnvInfoFunction) {}++    public initialize(): void {+        this.persistentStorage = createGlobalPersistentStore<PythonEnvInfo[]>('PYTHON_ENV_INFO_CACHE');+        this.envsList = this.persistentStorage?.value;+    }++    public getAllEnvs(): PythonEnvInfo[] | undefined {+        return this.envsList;+    }++    public setAllEnvs(envs: PythonEnvInfo[]): void {+        this.envsList = cloneDeep(envs);+    }++    public getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined {+        // Retrieve all keys with non-undefined values.+        type EnvParamKeys = keyof typeof env;+        const keys = (Object.keys(env) as unknown as EnvParamKeys[]).filter((key) => env[key] !== undefined);++        // Return the first object where the values match env's.+        return this.envsList?.find((info) => {+            // Check if there is any mismatch between the values of the in-memory info and env.+            const mismatch = keys.some((key) => info[key] !== env[key]);++            return !mismatch;+        });+    }

Two different environments can have the same env.executable.filename but otherwise have some different info (like kind).

kimadeline

comment created time in 4 days

PullRequestReviewEvent

push eventericsnowcurrently/vscode-python

Eric Snow

commit sha 187549394fb470ab62da2e92deffd32e2983d7a5

Factor out getURIFilter().

view details

Eric Snow

commit sha 9d1f86c4586564029e3711d308959177bbe2a071

Allow locator queries to mix search locations and non.

view details

Eric Snow

commit sha 2367b140535c6c4fd5b4072946a7ef05802e32f8

Match subdirectories in locator queries.

view details

Eric Snow

commit sha c3e17e9b993da306ccc5bab162fee04e27f7928a

Make PythonVersion.release optional.

view details

Eric Snow

commit sha dbcddad760e6b69e5723296f4c872d95feb1e30c

Drop the fixPath() testing helper.

view details

Eric Snow

commit sha 5847336c14417ebf82799b72531787a1f2411162

lint

view details

push time in 4 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {+    private envsList: PythonEnvInfo[] | undefined;++    private persistentStorage: IPersistentState<PythonEnvInfo[]> | undefined;++    constructor(private readonly isComplete: CompleteEnvInfoFunction) {}++    public initialize(): void {+        this.persistentStorage = createGlobalPersistentStore<PythonEnvInfo[]>('PYTHON_ENV_INFO_CACHE');+        this.envsList = this.persistentStorage?.value;+    }++    public getAllEnvs(): PythonEnvInfo[] | undefined {+        return this.envsList;+    }++    public setAllEnvs(envs: PythonEnvInfo[]): void {+        this.envsList = cloneDeep(envs);+    }++    public getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined {+        // Retrieve all keys with non-undefined values.+        type EnvParamKeys = keyof typeof env;+        const keys = (Object.keys(env) as unknown as EnvParamKeys[]).filter((key) => env[key] !== undefined);++        // Return the first object where the values match env's.+        return this.envsList?.find((info) => {+            // Check if there is any mismatch between the values of the in-memory info and env.+            const mismatch = keys.some((key) => info[key] !== env[key]);++            return !mismatch;+        });+    }

They may be complete, but they do not have to have the same info.

kimadeline

comment created time in 4 days

PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;

by declaring them as async now we force the caller function to be async as well ... what would be stopping us from declaring everything from now on as async?

Yep, this is my big complaint about async, in a nutshell! It's an infection that slowly spreads. 😄

Regardless, in this case I was thinking about the general abstraction of the "cache". I would expect all of it's methods to be async. I'm quite surprised that initialize() doesn't have to be. I don't mind leaving them not-async, but wanted to be sure we had considered the cost of not making them async now (solely based on our implementation), especially since it's easy to imagine an implementation that does need async. It sounds like you are confident that it is easy to switch to async later. That hasn't been my experience in the extension, but I'm willing to trust you. 😄

kimadeline

comment created time in 4 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

 export class PythonEnvironments implements ILocator {  */ export function createAPI(): [PythonEnvironments, () => void] {     const [locators, activateLocators] = initLocators();+    // Update this to pass in an actual function that checks for env info completeness.+    const envsCache = new PythonEnvInfoCache(() => true);

I figured we were leaving links to github issues in the code rather than AzDO tasks. At the same time, we also need a task to track the actual work.

kimadeline

comment created time in 4 days

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {+    private envsList: PythonEnvInfo[] | undefined;++    private persistentStorage: IPersistentState<PythonEnvInfo[]> | undefined;++    constructor(private readonly isComplete: CompleteEnvInfoFunction) {}++    public initialize(): void {+        this.persistentStorage = createGlobalPersistentStore<PythonEnvInfo[]>('PYTHON_ENV_INFO_CACHE');+        this.envsList = this.persistentStorage?.value;+    }++    public getAllEnvs(): PythonEnvInfo[] | undefined {+        return this.envsList;+    }++    public setAllEnvs(envs: PythonEnvInfo[]): void {+        this.envsList = cloneDeep(envs);+    }++    public getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined {+        // Retrieve all keys with non-undefined values.+        type EnvParamKeys = keyof typeof env;+        const keys = (Object.keys(env) as unknown as EnvParamKeys[]).filter((key) => env[key] !== undefined);++        // Return the first object where the values match env's.+        return this.envsList?.find((info) => {+            // Check if there is any mismatch between the values of the in-memory info and env.+            const mismatch = keys.some((key) => info[key] !== env[key]);++            return !mismatch;+        });+    }

The problem is where we pass in a partial PythonEnvInfo that only has env.executable.filename set (a likely case in the extension). This may match multiple different conflicting environments. We need to decide which one to use rather than returning the first match.

kimadeline

comment created time in 4 days

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Environment info cache class

 export function arePathsSame(path1: string, path2: string): boolean {     }     return path1 === path2; }++function getPersistentStateFactory(): IPersistentStateFactory {+    return internalServiceContainer.get<IPersistentStateFactory>(IPersistentStateFactory);+}++export function createGlobalPersistentStore<T>(key: string): IPersistentState<T> {+    const factory = getPersistentStateFactory();++    return factory.createGlobalPersistentState<T>(key, undefined);+}

Fine with me. I just wanted to be sure we considered this.

kimadeline

comment created time in 4 days

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {+    private envsList: PythonEnvInfo[] | undefined;++    private persistentStorage: IPersistentState<PythonEnvInfo[]> | undefined;++    constructor(private readonly isComplete: CompleteEnvInfoFunction) {}++    public initialize(): void {+        this.persistentStorage = createGlobalPersistentStore<PythonEnvInfo[]>('PYTHON_ENV_INFO_CACHE');+        this.envsList = this.persistentStorage?.value;

this.defaultValue is undefined by default.

kimadeline

comment created time in 4 days

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {+    private envsList: PythonEnvInfo[] | undefined;++    private persistentStorage: IPersistentState<PythonEnvInfo[]> | undefined;++    constructor(private readonly isComplete: CompleteEnvInfoFunction) {}++    public initialize(): void {+        this.persistentStorage = createGlobalPersistentStore<PythonEnvInfo[]>('PYTHON_ENV_INFO_CACHE');

We've had discussion in the past about consolidating all the various storage keys into one place so we could monitor our use of storage better. That would involve pulling things like this out into a constant. So I suppose I was thinking along those lines. However, doing it halfway probably does not add much value, so don't worry about it. 😄

FWIW, I was going to point out the value of avoiding "magic" constants, but in this case I don't think it's as much of a concern.

kimadeline

comment created time in 4 days

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {+    private envsList: PythonEnvInfo[] | undefined;++    private persistentStorage: IPersistentState<PythonEnvInfo[]> | undefined;

I was talking about the API of the storage, not of PythonEnvInfoCache. Sorry for the confusion.

kimadeline

comment created time in 4 days

PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Added environments resolver

+// Copyright (c) Microsoft Corporation. All rights reserved.

As discussed, we agreed that these locators will go in src/client/pythonEnvironments/base/locators/composite/.

karrtikr

comment created time in 4 days

Pull request review commentmicrosoft/vscode-python

Added environments resolver

+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+import { cloneDeep } from 'lodash';
+import { Event, EventEmitter } from 'vscode';
+import { traceVerbose } from '../../common/logger';
+import { areSameEnvironment, PythonEnvInfo } from '../base/info';
+import { InterpreterInformation } from '../base/info/interpreter';
+import {
+    ILocator, IPythonEnvsIterator, PythonEnvUpdatedEvent, PythonLocatorQuery,
+} from '../base/locator';
+import { PythonEnvsChangedEvent } from '../base/watcher';
+import { IEnvironmentInfoService } from '../info/environmentInfoService';
+
+export class PythonEnvsResolver implements ILocator {

doc comment

karrtikr

comment created time in 4 days

Pull request review commentmicrosoft/vscode-python

Added environments resolver

+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+import { cloneDeep } from 'lodash';
+import { Event, EventEmitter } from 'vscode';
+import { traceVerbose } from '../../common/logger';
+import { areSameEnvironment, PythonEnvInfo } from '../base/info';
+import { InterpreterInformation } from '../base/info/interpreter';
+import {
+    ILocator, IPythonEnvsIterator, PythonEnvUpdatedEvent, PythonLocatorQuery,
+} from '../base/locator';
+import { PythonEnvsChangedEvent } from '../base/watcher';
+import { IEnvironmentInfoService } from '../info/environmentInfoService';
+
+export class PythonEnvsResolver implements ILocator {
+    public get onChanged(): Event<PythonEnvsChangedEvent> {
+        return this.parentLocator.onChanged;
+    }
+
+    constructor(
+        private readonly parentLocator: ILocator,
+        private readonly environmentInfoService: IEnvironmentInfoService,
+    ) {}
+
+    public async resolveEnv(env: string | PythonEnvInfo): Promise<PythonEnvInfo | undefined> {
+        const environment = await this.parentLocator.resolveEnv(env);
+        if (!environment) {
+            return undefined;
+        }
+        const interpreterInfo = await this.environmentInfoService.getEnvironmentInfo(environment.executable.filename);
+        if (!interpreterInfo) {
+            return undefined;
+        }
+        return getResolvedEnv(interpreterInfo, environment);
+    }
+
+    public iterEnvs(query?: PythonLocatorQuery): IPythonEnvsIterator {
+        const didUpdate = new EventEmitter<PythonEnvUpdatedEvent | null>();
+        const incomingIterator = this.parentLocator.iterEnvs(query);
+        const iterator: IPythonEnvsIterator = this.iterEnvsIterator(incomingIterator, didUpdate);
+        iterator.onUpdated = didUpdate.event;
+        return iterator;
+    }
+
+    private async* iterEnvsIterator(
+        iterator: IPythonEnvsIterator,
+        didUpdate: EventEmitter<PythonEnvUpdatedEvent | null>,
+    ): AsyncIterator<PythonEnvInfo, void> {
+        const state = {
+            done: false,
+            pending: 0,
+        };
+        const seen: PythonEnvInfo[] = [];
+
+        if (iterator.onUpdated !== undefined) {
+            iterator.onUpdated((event) => {
+                if (event === null) {
+                    state.done = true;
+                    checkIfFinishedAndNotify(state, didUpdate);
+                } else {
+                    const oldIndex = seen.findIndex((s) => areSameEnvironment(s, event.old));
+                    if (oldIndex !== -1) {
+                        seen[oldIndex] = event.new;
+                        state.pending += 1;
+                        this.resolveInBackground(oldIndex, state, didUpdate, seen).ignoreErrors();
+                    } else {
+                        // This implies a problem in a downstream locator
+                        traceVerbose(`Expected already iterated env in resolver, got ${event.old}`);
+                    }
+                }
+            });
+        }
+
+        let result = await iterator.next();
+        while (!result.done) {
+            const currEnv = result.value;
+            // Resolver only expects unique environments, so store & yield as-is.

This comment doesn't add much. I'd drop it.

karrtikr

comment created time in 4 days

PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Added environments resolver

+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+import { cloneDeep } from 'lodash';
+import { Event, EventEmitter } from 'vscode';
+import { traceVerbose } from '../../common/logger';
+import { areSameEnvironment, PythonEnvInfo } from '../base/info';
+import { InterpreterInformation } from '../base/info/interpreter';
+import {
+    ILocator, IPythonEnvsIterator, PythonEnvUpdatedEvent, QueryForEvent,
+} from '../base/locator';
+import { PythonEnvsChangedEvent } from '../base/watcher';
+import { IEnvironmentInfoService } from '../info/environmentInfoService';
+
+export class PythonEnvsResolver implements ILocator {
+    public get onChanged(): Event<PythonEnvsChangedEvent> {
+        return this.pythonEnvsReducer.onChanged;
+    }
+
+    constructor(
+        private readonly pythonEnvsReducer: ILocator,
+        private readonly environmentInfoService: IEnvironmentInfoService,

I'm not sure that's still the case, but I'm not going to block on this.

karrtikr

comment created time in 5 days

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Added environments resolver

+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+import { assert, expect } from 'chai';
+import { cloneDeep } from 'lodash';
+import * as path from 'path';
+import { ImportMock } from 'ts-mock-imports';
+import { EventEmitter } from 'vscode';
+import { ExecutionResult } from '../../../client/common/process/types';
+import { Architecture } from '../../../client/common/utils/platform';
+import { PythonEnvInfo, PythonEnvKind } from '../../../client/pythonEnvironments/base/info';
+import { parseVersion } from '../../../client/pythonEnvironments/base/info/pythonVersion';
+import { PythonEnvUpdatedEvent } from '../../../client/pythonEnvironments/base/locator';
+import { PythonEnvsChangedEvent } from '../../../client/pythonEnvironments/base/watcher';
+import { PythonEnvsResolver } from '../../../client/pythonEnvironments/collection/environmentsResolver';
+import * as ExternalDep from '../../../client/pythonEnvironments/common/externalDependencies';
+import { EnvironmentInfoService } from '../../../client/pythonEnvironments/info/environmentInfoService';
+import { sleep } from '../../core';
+import { createEnv, getEnvs, SimpleLocator } from '../base/common';
+
+suite('Environments Resolver', () => {
+    /**
+     * Returns the expected environment to be returned by Environment info service
+     */
+    function createExpectedEnvInfo(env: PythonEnvInfo): PythonEnvInfo {
+        const updatedEnv = cloneDeep(env);
+        updatedEnv.version = {
+            ...parseVersion('3.8.3-final'),
+            sysVersion: '3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:37:02) [MSC v.1924 64 bit (AMD64)]',
+        };
+        updatedEnv.executable.filename = env.executable.filename;
+        updatedEnv.executable.sysPrefix = 'path';
+        updatedEnv.arch = Architecture.x64;
+        return updatedEnv;
+    }
+    suite('iterEnvs()', () => {
+        let stubShellExec: sinon.SinonStub;

I'm not going to block on this, but I'm uncomfortable with having our tests rely on seemingly unrelated external dependencies. It feels a bit fragile and magjcal and requires that readers of the tests puzzle out why the tests require mocking out some random function.

karrtikr

comment created time in 5 days

PullRequestReviewEvent

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {+    private envsList: PythonEnvInfo[] | undefined;++    private persistentStorage: IPersistentState<PythonEnvInfo[]> | undefined;++    constructor(private readonly isComplete: CompleteEnvInfoFunction) {}++    public initialize(): void {+        this.persistentStorage = createGlobalPersistentStore<PythonEnvInfo[]>('PYTHON_ENV_INFO_CACHE');+        this.envsList = this.persistentStorage?.value;+    }++    public getAllEnvs(): PythonEnvInfo[] | undefined {+        return this.envsList;

I'd expect to get a copy of the array, and possibly a deep-copy of each env.

kimadeline

comment created time in 5 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {+    private envsList: PythonEnvInfo[] | undefined;++    private persistentStorage: IPersistentState<PythonEnvInfo[]> | undefined;++    constructor(private readonly isComplete: CompleteEnvInfoFunction) {}++    public initialize(): void {+        this.persistentStorage = createGlobalPersistentStore<PythonEnvInfo[]>('PYTHON_ENV_INFO_CACHE');+        this.envsList = this.persistentStorage?.value;

What is this value if nothing has been stored yet? From the type I'd guess an empty array, but in practice I'd expect undefined.

This is a relatively important question because if getAllEnvs() returns undefined then it means nothing has been set yet. Returning an empty array means it was previously set to an empty array. An empty array means there aren't any Python environments, whereas undefined means we don't know yet.

So if we're getting an empty array if storage hasn't been set yet then we'll need to do some shenanigans to return undefined in that case.

kimadeline

comment created time in 5 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {+    private envsList: PythonEnvInfo[] | undefined;++    private persistentStorage: IPersistentState<PythonEnvInfo[]> | undefined;++    constructor(private readonly isComplete: CompleteEnvInfoFunction) {}++    public initialize(): void {+        this.persistentStorage = createGlobalPersistentStore<PythonEnvInfo[]>('PYTHON_ENV_INFO_CACHE');+        this.envsList = this.persistentStorage?.value;+    }++    public getAllEnvs(): PythonEnvInfo[] | undefined {+        return this.envsList;+    }++    public setAllEnvs(envs: PythonEnvInfo[]): void {+        this.envsList = cloneDeep(envs);+    }++    public getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined {+        // Retrieve all keys with non-undefined values.+        type EnvParamKeys = keyof typeof env;+        const keys = (Object.keys(env) as unknown as EnvParamKeys[]).filter((key) => env[key] !== undefined);++        // Return the first object where the values match env's.+        return this.envsList?.find((info) => {+            // Check if there is any mismatch between the values of the in-memory info and env.+            const mismatch = keys.some((key) => info[key] !== env[key]);++            return !mismatch;+        });+    }

Regardless, you're still left with problem which needs to be solved sooner rather than later, if not in this PR. Here's the problem: when "env" matches more than one of the cached envs, getEnv() here must decide which one gets returned. Currently you are returning the first match. However, we need it to select the "best match". That operation is not the responsibility of the cache so you should expect it to be provided for you. (It actually belongs to the reducer). So PythonEnvInfoCache should delegate to an "external" function, either imported or passed in to getEnv() or to the constructor (my preference). Two options for the helper:

  • findMatchingEnv(env: Partial<PythonEnvInfo>, candidates: PythonEnvInfo[]): PythonEnvInfo | undefined
  • pickBestEnv(candidates: PythonEnvInfo[]): PythonEnvInfo (would require filtering through areSameEnv() first)

We could also just return undefined if there are multiple matches and let the caller (e.g. CachingLocator deal with it, but then we'd lose the list of cached envs that match. In that case I doubt we would use getEnv() in the first place. That would be a negative though since getEnvs() exists as a potential point of optimization. So I'd rather we go the helper route.

kimadeline

comment created time in 5 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

 export function arePathsSame(path1: string, path2: string): boolean {     }     return path1 === path2; }++function getPersistentStateFactory(): IPersistentStateFactory {+    return internalServiceContainer.get<IPersistentStateFactory>(IPersistentStateFactory);+}++export function createGlobalPersistentStore<T>(key: string): IPersistentState<T> {+    const factory = getPersistentStateFactory();++    return factory.createGlobalPersistentState<T>(key, undefined);+}

(Heads up: I'm pointing out a broader concern here rather than anything to necessarily change.)

Using the existing PersistentStore API involves several levels of indirection without adding much value. We should look at using PersistentStore directly or perhaps deal vscode.Memento directly or add a simpler wrapper here. The key thing is that ideally this file stay as close to our actual external dependencies as possible. In this case that would be vscode.Memento.

kimadeline

comment created time in 5 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {+    private envsList: PythonEnvInfo[] | undefined;++    private persistentStorage: IPersistentState<PythonEnvInfo[]> | undefined;++    constructor(private readonly isComplete: CompleteEnvInfoFunction) {}++    public initialize(): void {+        this.persistentStorage = createGlobalPersistentStore<PythonEnvInfo[]>('PYTHON_ENV_INFO_CACHE');+        this.envsList = this.persistentStorage?.value;+    }++    public getAllEnvs(): PythonEnvInfo[] | undefined {+        return this.envsList;+    }++    public setAllEnvs(envs: PythonEnvInfo[]): void {+        this.envsList = cloneDeep(envs);+    }++    public getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined {+        // Retrieve all keys with non-undefined values.+        type EnvParamKeys = keyof typeof env;+        const keys = (Object.keys(env) as unknown as EnvParamKeys[]).filter((key) => env[key] !== undefined);++        // Return the first object where the values match env's.+        return this.envsList?.find((info) => {

I'm on the fence about it, but we should be sure it's okay to not return a deep copy.

kimadeline

comment created time in 5 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import * as assert from 'assert';+import * as sinon from 'sinon';+import { CompleteEnvInfoFunction, PythonEnvInfoCache } from '../../../client/pythonEnvironments/base/envsCache';+import { PythonEnvInfo, PythonEnvKind } from '../../../client/pythonEnvironments/base/info';+import * as externalDeps from '../../../client/pythonEnvironments/common/externalDependencies';++suite('Environment Info cache', () => {+    let createGlobalPersistentStoreStub: sinon.SinonStub;+    let updatedValues: PythonEnvInfo[] | undefined;++    const allEnvsComplete: CompleteEnvInfoFunction = () => true;+    const envInfoArray = [+        {+            id: 'someid1', kind: PythonEnvKind.Conda, name: 'my-conda-env', defaultDisplayName: 'env-one',+        },+        {+            id: 'someid2', kind: PythonEnvKind.Venv, name: 'my-venv-env', defaultDisplayName: 'env-two',+        },+        {+            id: 'someid3', kind: PythonEnvKind.Pyenv, name: 'my-pyenv-env', defaultDisplayName: 'env-three',

FYI, I'm dropping PythonEnvInfo.id in #14051.

kimadeline

comment created time in 5 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {+    private envsList: PythonEnvInfo[] | undefined;++    private persistentStorage: IPersistentState<PythonEnvInfo[]> | undefined;++    constructor(private readonly isComplete: CompleteEnvInfoFunction) {}++    public initialize(): void {+        this.persistentStorage = createGlobalPersistentStore<PythonEnvInfo[]>('PYTHON_ENV_INFO_CACHE');+        this.envsList = this.persistentStorage?.value;

Hmm, it looks like the old PersistentState implementation returns undefined even though it says it is returning PythonEnvInfo[]. So I'd suggest making the "external" createGlobalPersistentStore() helper return something more accurate, like this:

interface IPersistentStore<T> {
    value: T | undefined;
    updateValue(v: T): Promise<void>;
}

or while you're at it, make it a bit more sensible:

interface IPersistentStore<T> {
    get(): T | undefined; // maybe even make it async...
    set(v: T): Promise<void>;
}

You could also try the signature of the vscode.Memento type, but a wrapper like PersistentStore is still probably a better fit.

kimadeline

comment created time in 5 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {+    private envsList: PythonEnvInfo[] | undefined;++    private persistentStorage: IPersistentState<PythonEnvInfo[]> | undefined;++    constructor(private readonly isComplete: CompleteEnvInfoFunction) {}++    public initialize(): void {+        this.persistentStorage = createGlobalPersistentStore<PythonEnvInfo[]>('PYTHON_ENV_INFO_CACHE');+        this.envsList = this.persistentStorage?.value;+    }++    public getAllEnvs(): PythonEnvInfo[] | undefined {+        return this.envsList;+    }++    public setAllEnvs(envs: PythonEnvInfo[]): void {+        this.envsList = cloneDeep(envs);+    }++    public getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined {+        // Retrieve all keys with non-undefined values.+        type EnvParamKeys = keyof typeof env;+        const keys = (Object.keys(env) as unknown as EnvParamKeys[]).filter((key) => env[key] !== undefined);++        // Return the first object where the values match env's.+        return this.envsList?.find((info) => {+            // Check if there is any mismatch between the values of the in-memory info and env.+            const mismatch = keys.some((key) => info[key] !== env[key]);++            return !mismatch;+        });+    }

Ideally "env" would contain enough information to identify the env uniquely. In that case there would be at most one match, rather than just a "first" one. However, without some help that isn't an option and your implementation seems like a reasonable starting point.

FYI, @karthiknadig is already working on a areSameEnv() function in #14026, which you should use as soon as it's available. The only catch is that it does not support Partial<PythonEnvInfo> for either arg. That would have to be fixed before you could use it or we'd need a separate mayBeSameEnv(env1: Partial<PythonEnvInfo>, env2: Partial<PythonEnvInfo>): boolean. Either way I think that would be worth doing. While waiting you could factor out your current implementation into a similar local helper, to be replaced once areSameEnv() is available.

kimadeline

comment created time in 5 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;

Why are we exporting this? It doesn't really have any value for re-usability, does it.

kimadeline

comment created time in 5 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

 export function arePathsSame(path1: string, path2: string): boolean {     }     return path1 === path2; }++function getPersistentStateFactory(): IPersistentStateFactory {+    return internalServiceContainer.get<IPersistentStateFactory>(IPersistentStateFactory);+}++export function createGlobalPersistentStore<T>(key: string): IPersistentState<T> {

Just to be sure I understand, this only creates the storage if it doesn't exist already, right? If so, "create" in the name seems as bit misleading. Consider something more like "ensureGlobalPersistentStore".

kimadeline

comment created time in 5 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {+    private envsList: PythonEnvInfo[] | undefined;++    private persistentStorage: IPersistentState<PythonEnvInfo[]> | undefined;++    constructor(private readonly isComplete: CompleteEnvInfoFunction) {}++    public initialize(): void {+        this.persistentStorage = createGlobalPersistentStore<PythonEnvInfo[]>('PYTHON_ENV_INFO_CACHE');+        this.envsList = this.persistentStorage?.value;

I'm curious how updateValue() as async but this isn't. (This has nothing to do with your PR. It's more a reflection on the confusing PersistentStorage API. 😄)

kimadeline

comment created time in 5 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {+    private envsList: PythonEnvInfo[] | undefined;++    private persistentStorage: IPersistentState<PythonEnvInfo[]> | undefined;++    constructor(private readonly isComplete: CompleteEnvInfoFunction) {}++    public initialize(): void {+        this.persistentStorage = createGlobalPersistentStore<PythonEnvInfo[]>('PYTHON_ENV_INFO_CACHE');

Consider moving that key to a global constant.

kimadeline

comment created time in 5 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;

FWIW, I expected these operations to be async. Our implementation may not require async now, but how sure are we that that won't change? It seems like a consistent pain point when we have to convert a public API like this to async after we've started using it.

So I guess my question is: what would be the problem with declaring them as async now?

kimadeline

comment created time in 5 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {

doc comment

kimadeline

comment created time in 5 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {+    private envsList: PythonEnvInfo[] | undefined;++    private persistentStorage: IPersistentState<PythonEnvInfo[]> | undefined;++    constructor(private readonly isComplete: CompleteEnvInfoFunction) {}++    public initialize(): void {

I recommend making this operation idempotent:

    public initialize(): void {
        if (this.initialized) {
            return;
        }
        this.initialized = true;
kimadeline

comment created time in 5 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

+// Copyright (c) Microsoft Corporation. All rights reserved.+// Licensed under the MIT License.++import { cloneDeep } from 'lodash';+import { IPersistentState } from '../../common/types';+import { createGlobalPersistentStore } from '../common/externalDependencies';+import { PythonEnvInfo } from './info';++/**+ * Represents the environment info cache to be used by the cache locator.+ */+export interface IEnvsCache {+    /**+     * Initialization logic to be done outside of the constructor, for example reading from persistent storage.+     */+    initialize(): void;++    /**+     * Return all environment info currently in memory for this session.+     *+     * @return An array of cached environment info, or `undefined` if there are none.+     */+    getAllEnvs(): PythonEnvInfo[] | undefined;++    /**+     * Replace all environment info currently in memory for this session.+     *+     * @param envs The array of environment info to store in the in-memory cache.+     */+    setAllEnvs(envs: PythonEnvInfo[]): void;++    /**+     * Return a specific environmnent info object.+     *+     * @param env The environment info data that will be used to look for an environment info object in the cache.+     * This object may contain incomplete environment info.+     * @return The environment info object that matches all non-undefined keys from the `env` param,+     *  `undefined` otherwise.+     */+    getEnv(env: Partial<PythonEnvInfo>): PythonEnvInfo | undefined;++    /**+     * Writes the content of the in-memory cache to persistent storage.+     */+    flush(): Promise<void>;+}++export type CompleteEnvInfoFunction = (envInfo: PythonEnvInfo) => boolean;++export class PythonEnvInfoCache implements IEnvsCache {+    private envsList: PythonEnvInfo[] | undefined;++    private persistentStorage: IPersistentState<PythonEnvInfo[]> | undefined;

There is some merit to focusing on specific local needs rather than coupling our implementation to an existing API. It's a matter of implementing against our needs rather than against the available tools. (We can always adapt between our needs and available tools separately.) For example, here I'd find something like the following to be more clear.

interface EnvsStorage {
    getEnvs(): Promise<PythonEnvInfo[]>;
    setEnvs(envs: PythonEnvInfo[]): Promise<void>;
}

That said, in this case I don't think it's a big enough deal to worry about, especially since the coupled API isn't leaking out into the public members of PythonEnvInfoCache. I suppose I just wanted to offer something to think about. 😄

kimadeline

comment created time in 5 days

Pull request review commentmicrosoft/vscode-python

Environment info cache class

 export class PythonEnvironments implements ILocator {  */ export function createAPI(): [PythonEnvironments, () => void] {     const [locators, activateLocators] = initLocators();+    // Update this to pass in an actual function that checks for env info completeness.+    const envsCache = new PythonEnvInfoCache(() => true);

We should add an issue + task for this.

kimadeline

comment created time in 5 days

PullRequestReviewEvent
PullRequestReviewEvent
more