From 26fee7d229e8356041d30c19e1adaec4f59170f8 Mon Sep 17 00:00:00 2001 From: Wasim Lorgat Date: Fri, 8 Mar 2024 04:15:53 -0600 Subject: [PATCH] Extract positron-ipykernel CI and test requirements, re-add ruff and prettier checks (posit-dev/positron-python#416) * unpin pytest our reason for pinning has been fixed upstream in https://github.com/microsoft/vscode-python/pull/22799. also bump pytest-asyncio to a compatible version. * extract positron-ipykernel ci job and test requirements * remove pillow - it's another snyk pin * remove unusued test requirements * re-add pyright job * re-add ruff to ci lint job * re-add format-check; downgrade prettier to match upstream; fix format errors * checkout before setting up pip cache --- .../.github/workflows/positron-ci.yml | 165 ++++++++++++++---- extensions/positron-python/build/constants.js | 3 +- .../build/pinned-test-requirements.txt | 43 ----- .../build/test-requirements.txt | 34 +--- .../webpack.extension.browser.config.js | 4 +- extensions/positron-python/package.json | 2 +- .../positron/pinned-test-requirements.txt | 14 ++ .../positron_ipykernel/data_explorer.py | 2 +- .../positron_ipykernel/docstrings/epytext.py | 2 +- .../positron/positron_ipykernel/jedi.py | 6 +- .../positron/positron_ipykernel/pydoc.py | 8 +- .../tests/test_data_explorer.py | 20 +-- .../positron_ipykernel/tests/test_help.py | 2 +- .../tests/test_inspectors.py | 12 +- .../positron_ipykernel/tests/test_plots.py | 2 +- .../positron_ipykernel/tests/test_widget.py | 3 - .../positron/positron_ipykernel/ui.py | 2 +- .../positron/test-requirements.txt | 11 ++ .../pythonFiles/pyproject.toml | 9 +- .../client/activation/jedi/analysisOptions.ts | 10 +- .../activation/jedi/languageClientFactory.ts | 2 +- .../activation/jedi/languageServerProxy.ts | 2 +- .../diagnostics/checks/pythonInterpreter.ts | 6 +- .../src/client/common/configSettings.ts | 38 ++-- .../src/client/common/constants.ts | 2 +- .../shellDetectors/baseShellDetector.ts | 2 +- .../src/client/common/types.ts | 8 +- .../configuration/environmentTypeComparer.ts | 9 +- .../src/client/positron/provider.ts | 6 +- .../src/client/positron/runtime.ts | 47 ++--- .../src/client/positron/util.ts | 19 +- .../common/externalDependencies.ts | 3 +- .../checks/pythonInterpreter.unit.test.ts | 22 +-- .../installer/productInstaller.unit.test.ts | 1 - .../test/common/serviceRegistry.unit.test.ts | 2 +- .../environmentTypeComparer.unit.test.ts | 68 ++++---- .../positron-python/src/test/initialize.ts | 2 +- .../common/externalDependencies.unit.test.ts | 24 +-- .../terminals/serviceRegistry.unit.test.ts | 6 +- extensions/positron-python/yarn.lock | 8 +- 40 files changed, 324 insertions(+), 307 deletions(-) delete mode 100644 extensions/positron-python/build/pinned-test-requirements.txt create mode 100644 extensions/positron-python/pythonFiles/positron/pinned-test-requirements.txt create mode 100644 extensions/positron-python/pythonFiles/positron/test-requirements.txt diff --git a/extensions/positron-python/.github/workflows/positron-ci.yml b/extensions/positron-python/.github/workflows/positron-ci.yml index e14d2cd53747..6c4863921f98 100644 --- a/extensions/positron-python/.github/workflows/positron-ci.yml +++ b/extensions/positron-python/.github/workflows/positron-ci.yml @@ -1,4 +1,4 @@ -name: "Positron Python CI" +name: 'Positron Python CI' on: push: @@ -33,6 +33,12 @@ jobs: - name: Install Yarn run: npm install -g yarn + - name: Install Python ${{ env.PYTHON_VERSION }} + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + cache: 'pip' + - name: Install Node dependencies run: yarn install --immutable --network-timeout 120000 --prefer-offline @@ -45,68 +51,159 @@ jobs: - name: Lint TypeScript code run: yarn lint - - name: Install Python ${{ env.PYTHON_VERSION }} - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - cache: 'pip' + - name: Check TypeScript format + run: yarn format-check - name: Check Python format run: | python -m pip install -U black - python -m black . --check --include "positron\/.*.py$|positron_language_server.py$|tests\/test_positron_.*.py$" + python -m black . --check working-directory: pythonFiles + - name: Run Ruff + run: | + python -m pip install -U ruff + python -m ruff check . + working-directory: pythonFiles + + check-types: + name: Check Python types + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Use Python ${{ env.PYTHON_VERSION }} + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + cache: 'pip' + + - name: Install base Python requirements + uses: brettcannon/pip-secure-install@v1 + with: + options: '-t ./pythonFiles/lib/python --no-cache-dir --implementation py' + + - name: Install Positron IPyKernel requirements + run: python scripts/vendor.py + + - name: Install other Python requirements + run: | + python -m pip --disable-pip-version-check install -t ./pythonFiles/lib/python --no-cache-dir --implementation py --no-deps --upgrade --pre debugpy + python -m pip install --upgrade -r build/test-requirements.txt + python -m pip install --upgrade -r pythonFiles/positron/pinned-test-requirements.txt + + - name: Run Pyright + uses: jakebailey/pyright-action@v2 + with: + version: 1.1.352 + working-directory: 'pythonFiles' + python-tests: - name: Test Python + name: Python Tests + # The value of runs-on is the OS of the current job (specified in the strategy matrix below) instead of being hardcoded. runs-on: ${{ matrix.os }} + defaults: + run: + working-directory: ${{ env.special-working-directory }} strategy: + fail-fast: false matrix: + # TODO: Decide whether we want to match upstream matrix. + # # We're not running CI on macOS for now because it's one less matrix entry to lower the number of runners used, + # # macOS runners are expensive, and we assume that Ubuntu is enough to cover the Unix case. + # os: [ubuntu-latest, windows-latest] + # # Run the tests on the oldest and most recent versions of Python. + # python: ['3.8', '3.x'] # run for 3 pytest versions, most recent stable, oldest version supported and pre-release + # pytest-version: ['pytest', 'pytest@pre-release', 'pytest==6.2.0'] include: - os: 'ubuntu-latest' - python-version: '3.8' + python: '3.8' + pytest-version: 'pytest' - os: 'macos-latest' - python-version: '3.9' + python: '3.9' + pytest-version: 'pytest' - os: 'windows-latest' - python-version: '3.10' + python: '3.10' + pytest-version: 'pytest' - os: 'ubuntu-latest' - python-version: '3.11' + python: '3.11' + pytest-version: 'pytest' - os: 'ubuntu-latest' - python-version: '3.12' + python: '3.12' + pytest-version: 'pytest' + steps: - name: Checkout uses: actions/checkout@v4 - - - name: Use Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 with: - python-version: ${{ matrix.python-version }} - cache: 'pip' + path: ${{ env.special-working-directory-relative }} - - name: Install Python requirements - uses: brettcannon/pip-secure-install@v1 + - name: Use Python ${{ matrix.python }} + uses: actions/setup-python@v5 with: - options: '-t ./pythonFiles/lib/python --no-cache-dir --implementation py' + python-version: ${{ matrix.python }} - - name: Install Jedi requirements - run: python scripts/vendor.py + - name: Install specific pytest version + if: matrix.pytest-version == 'pytest@pre-release' + run: | + python -m pip install --pre pytest - - name: Install test requirements + - name: Install specific pytest version + if: matrix.pytest-version != 'pytest@pre-release' run: | - python -m pip --disable-pip-version-check install -t ./pythonFiles/lib/python --no-cache-dir --implementation py --no-deps --upgrade --pre debugpy - python -m pip install --prefer-binary --upgrade -r build/pinned-test-requirements.txt + python -m pip install "${{ matrix.pytest-version }}" - - name: Run Pyright - uses: jakebailey/pyright-action@v1 + - name: Install specific pytest version + run: python -m pytest --version + - name: Install base Python requirements + uses: brettcannon/pip-secure-install@v1 with: - working-directory: 'pythonFiles' + requirements-file: '"${{ env.special-working-directory-relative }}/requirements.txt"' + options: '-t "${{ env.special-working-directory-relative }}/pythonFiles/lib/python" --no-cache-dir --implementation py' - - name: Run Positron unit tests - run: pytest pythonFiles/positron/ + - name: Install test requirements + run: python -m pip install --upgrade -r build/test-requirements.txt - - name: Run Microsoft unit tests + - name: Run Python unit tests run: python pythonFiles/tests/run_all.py + positron-ipykernel-tests: + name: Test Positron IPyKernel + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: 'ubuntu-latest' + python: '3.8' + - os: 'macos-latest' + python: '3.9' + - os: 'windows-latest' + python: '3.10' + - os: 'ubuntu-latest' + python: '3.11' + - os: 'ubuntu-latest' + python: '3.12' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Use Python ${{ matrix.python }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + cache: 'pip' + + - name: Install Positron IPyKernel requirements + run: python scripts/vendor.py + + - name: Install Positron IPyKernel test requirements + run: python -m pip install --prefer-binary --upgrade -r pythonFiles/positron/pinned-test-requirements.txt + + - name: Run Positron IPyKernel unit tests + run: pytest pythonFiles/positron + typescript-tests: name: Test TypeScript runs-on: ${{ matrix.os }} @@ -139,7 +236,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 with: - path: ${{ env.special-working-directory-relative }} + path: ${{ env.special-working-directory-relative }} - name: Install Node ${{ env.NODE_VERSION }} uses: actions/setup-node@v3 @@ -167,7 +264,7 @@ jobs: run: npx @vscode/l10n-dev@latest export ./src - name: Install test requirements - run: python -m pip install --upgrade -r ./build/pinned-test-requirements.txt + run: python -m pip install --upgrade -r ./build/test-requirements.txt - name: Install functional test requirements run: python -m pip install --upgrade -r ./build/functional-test-requirements.txt diff --git a/extensions/positron-python/build/constants.js b/extensions/positron-python/build/constants.js index 086ad5af6f15..da6139ff1c99 100644 --- a/extensions/positron-python/build/constants.js +++ b/extensions/positron-python/build/constants.js @@ -11,5 +11,6 @@ exports.existingFiles = util.getListOfFiles('existingFiles.json'); exports.contributedFiles = util.getListOfFiles('contributedFiles.json'); exports.isWindows = /^win/.test(process.platform); // --- Start Positron --- -exports.isCI = process.env.GITHUB_ACTIONS === 'true' || process.env.TRAVIS === 'true' || process.env.TF_BUILD !== undefined; +exports.isCI = + process.env.GITHUB_ACTIONS === 'true' || process.env.TRAVIS === 'true' || process.env.TF_BUILD !== undefined; // --- End Positron --- diff --git a/extensions/positron-python/build/pinned-test-requirements.txt b/extensions/positron-python/build/pinned-test-requirements.txt deleted file mode 100644 index 1b3e99b52b02..000000000000 --- a/extensions/positron-python/build/pinned-test-requirements.txt +++ /dev/null @@ -1,43 +0,0 @@ -# pin setoptconf to prevent issue with 'use_2to3' -setoptconf==0.3.0 - -flake8==7.0.0 -bandit==1.7.7 -pylint==3.0.3 -pycodestyle==2.11.1 -pydocstyle==6.3.0 -pygls==1.3.0 -prospector==0.12.2 -pytest==8.0.2 -Flask==3.0.2 -fastapi==0.109.2 -uvicorn==0.27.0.post1 -Django==5.0.3; python_version >= '3.10' -Django==4.2.11; python_version < '3.10' -# Integrated TensorBoard tests -tensorboard==2.15.1; python_version >= '3.9' -tensorboard==2.14.0; python_version < '3.9' -torch-tb-profiler==0.4.3 -# extension build tests -freezegun==1.4.0 -# iPython Kernel tests -fastcore==1.5.29 -ipykernel==6.29.3 -ipywidgets==8.1.2 -matplotlib==3.8.2; python_version >= '3.9' -matplotlib==3.7.4; python_version < '3.9' -# Require fonttools >= 4.43.0 to avoid CVE-2023-45139 -fonttools==4.43.0 -numpy==1.26.3; python_version >= '3.9' -numpy==1.24.4; python_version < '3.9' -pandas==2.2.0; python_version >= '3.9' -pandas==2.0.3; python_version < '3.9' -# Require pillow >= 10.0.1 to avoid CVE-2023-4863 -pillow==10.2.0 -pyright==1.1.351 -pytest-asyncio==0.23.5 -pytest-mock==3.12.0 -polars==0.20.13 -torch==2.1.2; python_version < '3.12' -# Require wheel >= 0.38.0 to avoid CVE-2022-40898 -wheel==0.38.0 diff --git a/extensions/positron-python/build/test-requirements.txt b/extensions/positron-python/build/test-requirements.txt index 19b6df8aa77e..0650e86fb3d3 100644 --- a/extensions/positron-python/build/test-requirements.txt +++ b/extensions/positron-python/build/test-requirements.txt @@ -2,50 +2,20 @@ setoptconf==0.3.0 flake8 -# --- Start Positron --- -# Require bandit >= 1.7.7 to avoid CWE-89 -bandit>=1.7.7 -# --- End Positron --- +bandit pylint pycodestyle pydocstyle -pygls prospector pytest flask -# --- Start Positron --- -# Require fastapi >= 0.109.1 to avoid CVE-2024-24762 -fastapi>=0.109.1 -# --- End Positron --- +fastapi uvicorn django # Integrated TensorBoard tests -# --- Start Positron --- -# Require wheel >= 0.38.0 to avoid CVE-2022-40898 -wheel>=0.38.0 -# --- End Positron --- tensorboard torch-tb-profiler # extension build tests freezegun - -# --- Start Positron --- -# iPython Kernel tests -fastcore -# Require fonttools >= 4.43.0 to avoid CVE-2023-45139 -fonttools>=4.43.0 -ipykernel -ipywidgets -matplotlib -numpy -pandas -# Require pillow >= 10.0.1 to avoid CVE-2023-4863 -pillow>=10.0.1 -pyright -pytest-asyncio -pytest-mock -polars -torch; python_version < '3.12' -# --- End Positron --- diff --git a/extensions/positron-python/build/webpack/webpack.extension.browser.config.js b/extensions/positron-python/build/webpack/webpack.extension.browser.config.js index 8096bb2ab4e8..b4e0f17f185c 100644 --- a/extensions/positron-python/build/webpack/webpack.extension.browser.config.js +++ b/extensions/positron-python/build/webpack/webpack.extension.browser.config.js @@ -45,7 +45,7 @@ const nodeConfig = (_, { mode }) => ({ externals: { vscode: 'commonjs vscode', // --- Start Positron --- - 'positron': 'commonjs positron', // ignored because we inject positron via module loader + positron: 'commonjs positron', // ignored because we inject positron via module loader // --- End Positron --- // These dependencies are ignored because we don't use them, and App Insights has try-catch protecting their loading if they don't exist // See: https://github.com/microsoft/vscode-extension-telemetry/issues/41#issuecomment-598852991 @@ -54,7 +54,7 @@ const nodeConfig = (_, { mode }) => ({ // --- Start Positron --- '@opentelemetry/instrumentation': 'commonjs @opentelemetry/instrumentation', '@azure/opentelemetry-instrumentation-azure-sdk': 'commonjs @azure/opentelemetry-instrumentation-azure-sdk', - '@azure/functions-core': 'commonjs @azure/functions-core' + '@azure/functions-core': 'commonjs @azure/functions-core', // --- End Positron --- }, module: { diff --git a/extensions/positron-python/package.json b/extensions/positron-python/package.json index d38691dadd56..6033bbf85618 100644 --- a/extensions/positron-python/package.json +++ b/extensions/positron-python/package.json @@ -1700,7 +1700,7 @@ "node-loader": "^1.0.2", "node-polyfill-webpack-plugin": "^1.1.4", "nyc": "^15.0.0", - "prettier": "^2.0.2", + "prettier": "2.0.2", "rewiremock": "^3.13.0", "rimraf": "^3.0.2", "shortid": "^2.2.8", diff --git a/extensions/positron-python/pythonFiles/positron/pinned-test-requirements.txt b/extensions/positron-python/pythonFiles/positron/pinned-test-requirements.txt new file mode 100644 index 000000000000..c8b510b2ebaf --- /dev/null +++ b/extensions/positron-python/pythonFiles/positron/pinned-test-requirements.txt @@ -0,0 +1,14 @@ +fastcore==1.5.29 +ipykernel==6.29.3 +ipywidgets==8.1.2 +matplotlib==3.8.2; python_version >= '3.9' +matplotlib==3.7.4; python_version < '3.9' +numpy==1.26.3; python_version >= '3.9' +numpy==1.24.4; python_version < '3.9' +pandas==2.2.0; python_version >= '3.9' +pandas==2.0.3; python_version < '3.9' +pytest==8.0.2 +pytest-asyncio==0.23.5 +pytest-mock==3.12.0 +polars==0.20.13 +torch==2.1.2; python_version < '3.12' diff --git a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/data_explorer.py b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/data_explorer.py index 2190258a3f01..56bca99fcf25 100644 --- a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/data_explorer.py +++ b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/data_explorer.py @@ -686,7 +686,7 @@ def _fire_schema_update(discard_state=False): msg = SchemaUpdateParams(discard_state=discard_state) comm.send_event(DataExplorerFrontendEvent.SchemaUpdate.value, msg.dict()) - if type(new_table) is not type(table_view.table): + if type(new_table) is not type(table_view.table): # noqa: E721 # Data type has changed. For now, we will signal the UI to # reset its entire state: sorting keys, filters, etc. and # start over. At some point we can return here and diff --git a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/docstrings/epytext.py b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/docstrings/epytext.py index aabb86e7b780..044d0510966f 100644 --- a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/docstrings/epytext.py +++ b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/docstrings/epytext.py @@ -3,7 +3,7 @@ # import re -from textwrap import dedent, indent +from textwrap import dedent from typing import List # from markdown_to_docstring.google.ESCAPE_RULES diff --git a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/jedi.py b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/jedi.py index 006d84d944ab..cf5d9376698f 100644 --- a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/jedi.py +++ b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/jedi.py @@ -8,8 +8,8 @@ from ._vendor.jedi.api import Interpreter from ._vendor.jedi.api.classes import Completion from ._vendor.jedi.api.completion import ( - Completion as CompletionAPI, # Rename to avoid conflict with classes.Completion -) + Completion as CompletionAPI, +) # Rename to avoid conflict with classes.Completion from ._vendor.jedi.api.completion import ( _extract_string_while_in_string, _remove_duplicates, @@ -17,7 +17,7 @@ ) from ._vendor.jedi.api.file_name import complete_file_name from ._vendor.jedi.api.interpreter import MixedModuleContext -from ._vendor.jedi.api.strings import complete_dict, get_quote_ending +from ._vendor.jedi.api.strings import get_quote_ending from ._vendor.jedi.cache import memoize_method from ._vendor.jedi.file_io import KnownContentFileIO from ._vendor.jedi.inference.base_value import HasNoContext diff --git a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/pydoc.py b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/pydoc.py index c396de1a2466..d947a14c830f 100644 --- a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/pydoc.py +++ b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/pydoc.py @@ -765,7 +765,7 @@ def _pydoc_getdoc(object: Any) -> str: def _getdoc(object: Any) -> str: """Override `pydoc.getdoc` to parse reStructuredText docstrings.""" try: - docstring = _pydoc_getdoc(object) or f"No documentation found." + docstring = _pydoc_getdoc(object) or "No documentation found." html = _rst_to_html(docstring, object) except Exception as exception: # This is caught somewhere above us in pydoc. Log the exception so we see it in Positron @@ -786,7 +786,7 @@ def _resolve(target: str, from_obj: Any) -> Optional[str]: # Is `target` a module? try: importlib.import_module(target) - except: + except Exception: pass else: return target @@ -796,7 +796,7 @@ def _resolve(target: str, from_obj: Any) -> Optional[str]: module_path, object_path = target.rsplit(".", 1) try: module = importlib.import_module(module_path) - except: + except Exception: pass else: # Ignore all warnings that happen upon `hasattr(module, object_path)` e.g. @@ -818,7 +818,7 @@ def _resolve(target: str, from_obj: Any) -> Optional[str]: module_path, object_path = module_path.rsplit(".", 1) try: module = importlib.import_module(module_path) - except: + except Exception: pass else: obj = getattr(module, object_path, None) diff --git a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_data_explorer.py b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_data_explorer.py index 8dc657ca69de..2e47a077e587 100644 --- a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_data_explorer.py +++ b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_data_explorer.py @@ -8,20 +8,14 @@ import numpy as np import pandas as pd import pytest -from ..access_keys import encode_access_key + from .._vendor.pydantic import BaseModel +from ..access_keys import encode_access_key from ..data_explorer import COMPARE_OPS, DataExplorerService -from ..data_explorer_comm import ( - ColumnFilter, - ColumnSchema, - ColumnSortKey, - FilterResult, -) - +from ..data_explorer_comm import ColumnFilter, ColumnSchema, ColumnSortKey, FilterResult from .conftest import DummyComm, PositronShell -from .utils import json_rpc_notification, json_rpc_request, json_rpc_response - from .test_variables import BIG_ARRAY_LENGTH +from .utils import json_rpc_notification, json_rpc_request, json_rpc_response TARGET_NAME = "positron.dataExplorer" @@ -216,9 +210,9 @@ def _check_update_variable(name, update_type="schema", discard_state=True): ] if update_type == "schema": - expected_msg = json_rpc_notification(f"schema_update", {"discard_state": discard_state}) + expected_msg = json_rpc_notification("schema_update", {"discard_state": discard_state}) else: - expected_msg = json_rpc_notification(f"data_update", {}) + expected_msg = json_rpc_notification("data_update", {}) # Check that comms were all closed for comm in comms: @@ -382,7 +376,7 @@ def check_sort_case(self, table, sort_keys, expected_table, filters=None): self.set_column_filters(table_id, filters) response = self.set_sort_columns(table_id, sort_keys=sort_keys) - assert response == None + assert response is None self.compare_tables(table_id, ex_id, table.shape) def compare_tables(self, table_id: str, expected_id: str, table_shape: tuple): diff --git a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_help.py b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_help.py index c5f6b07145a8..c3b319d620fc 100644 --- a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_help.py +++ b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_help.py @@ -126,7 +126,7 @@ def test_show_help( params = data["params"] assert params["kind"] == "url" - assert params["focus"] == True + assert params["focus"] prefix = f"{url}get?key=" assert params["content"].startswith(prefix) assert params["content"][len(prefix) :] == expected_path diff --git a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_inspectors.py b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_inspectors.py index a13ddee75284..0c1f0af07e8a 100644 --- a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_inspectors.py +++ b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_inspectors.py @@ -14,15 +14,10 @@ import pandas as pd import polars as pl import pytest - from fastcore.foundation import L -from positron_ipykernel.inspectors import ( - PRINT_WIDTH, - TRUNCATE_AT, - get_inspector, -) +from positron_ipykernel.inspectors import PRINT_WIDTH, TRUNCATE_AT, get_inspector from positron_ipykernel.utils import get_qualname -from positron_ipykernel.variables_comm import Variable, VariableKind +from positron_ipykernel.variables_comm import VariableKind from .data import ( BOOL_CASES, @@ -36,7 +31,6 @@ STRING_CASES, TIMESTAMP_CASES, ) -from .utils import assert_pydantic_model_equal try: import torch # type: ignore [reportMissingImports] for 3.12 @@ -618,7 +612,7 @@ def test_inspect_numpy_array_0d(value: np.ndarray) -> None: value=value, display_value=np.array2string(value, separator=","), kind=VariableKind.Number, - display_type=f"numpy.int64", + display_type="numpy.int64", type_info="numpy.ndarray", is_truncated=True, length=0, diff --git a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_plots.py b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_plots.py index eb88736c70a2..3902e3960fe6 100644 --- a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_plots.py +++ b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_plots.py @@ -133,7 +133,7 @@ def test_hook_handle_msg_noop_on_unknown_method(figure_comm: DummyComm) -> None: figure_comm.handle_msg(msg) assert figure_comm.messages == [ - json_rpc_error(JsonRpcErrorCode.METHOD_NOT_FOUND, f"Unknown method 'not_render'") + json_rpc_error(JsonRpcErrorCode.METHOD_NOT_FOUND, "Unknown method 'not_render'") ] diff --git a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_widget.py b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_widget.py index 8445b653f9e4..9e5adb6fb520 100644 --- a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_widget.py +++ b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/tests/test_widget.py @@ -4,11 +4,8 @@ from typing import Iterable, cast -import comm -import ipywidgets as widgets import pytest from IPython.core.formatters import DisplayFormatter -from IPython.core.getipython import get_ipython from positron_ipykernel.widget import PositronWidgetHook from .conftest import DummyComm, PositronShell diff --git a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/ui.py b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/ui.py index bd87ada1a912..2242799a9838 100644 --- a/extensions/positron-python/pythonFiles/positron/positron_ipykernel/ui.py +++ b/extensions/positron-python/pythonFiles/positron/positron_ipykernel/ui.py @@ -87,7 +87,7 @@ def on_comm_open(self, comm: BaseComm, msg: JsonRecord) -> None: self._working_directory = None try: self.poll_working_directory() - except: + except Exception: logger.exception("Error polling working directory") def poll_working_directory(self) -> None: diff --git a/extensions/positron-python/pythonFiles/positron/test-requirements.txt b/extensions/positron-python/pythonFiles/positron/test-requirements.txt new file mode 100644 index 000000000000..89663e9363ea --- /dev/null +++ b/extensions/positron-python/pythonFiles/positron/test-requirements.txt @@ -0,0 +1,11 @@ +fastcore +ipykernel +ipywidgets +matplotlib +numpy +pandas +polars +pytest +pytest-asyncio +pytest-mock +torch; python_version < '3.12' diff --git a/extensions/positron-python/pythonFiles/pyproject.toml b/extensions/positron-python/pythonFiles/pyproject.toml index 151bee5fc451..201a33f66e48 100644 --- a/extensions/positron-python/pythonFiles/pyproject.toml +++ b/extensions/positron-python/pythonFiles/pyproject.toml @@ -53,8 +53,8 @@ ignore = [ ] [tool.ruff] -line-length = 140 -ignore = ["E402"] +line-length = 100 +lint.ignore = ["E402"] exclude = [ # Ignore testing_tools files same as Pyright way 'get-pip.py', @@ -80,6 +80,9 @@ exclude = [ 'pythonFiles/tests/pytestadapter/expected_execution_test_output.py', 'pythonFiles/tests/unittestadapter/.data/discovery_error/file_one.py', 'pythonFiles/tests/unittestadapter/test_utils.py', + # --- Start Positron --- # Ignore vendored dependencies - 'pythonFiles/positron/positron_ipykernel/_vendor/', + 'lib/python', + 'positron/positron_ipykernel/_vendor/', + # --- End Positron --- ] diff --git a/extensions/positron-python/src/client/activation/jedi/analysisOptions.ts b/extensions/positron-python/src/client/activation/jedi/analysisOptions.ts index c83f6635b60b..f017584c3a63 100644 --- a/extensions/positron-python/src/client/activation/jedi/analysisOptions.ts +++ b/extensions/positron-python/src/client/activation/jedi/analysisOptions.ts @@ -43,11 +43,11 @@ export class JediLanguageServerAnalysisOptions extends LanguageServerAnalysisOpt const workspacePath = this.getWorkspaceFolder()?.uri.fsPath; const extraPaths = pythonSettings.autoComplete ? pythonSettings.autoComplete.extraPaths.map((extraPath) => { - if (path.isAbsolute(extraPath)) { - return extraPath; - } - return workspacePath ? path.join(workspacePath, extraPath) : ''; - }) + if (path.isAbsolute(extraPath)) { + return extraPath; + } + return workspacePath ? path.join(workspacePath, extraPath) : ''; + }) : []; if (workspacePath) { diff --git a/extensions/positron-python/src/client/activation/jedi/languageClientFactory.ts b/extensions/positron-python/src/client/activation/jedi/languageClientFactory.ts index 68ec7e3ab0a6..c3ef8d9623f3 100644 --- a/extensions/positron-python/src/client/activation/jedi/languageClientFactory.ts +++ b/extensions/positron-python/src/client/activation/jedi/languageClientFactory.ts @@ -13,7 +13,7 @@ import { ILanguageClientFactory } from '../types'; const languageClientName = 'Python Jedi'; export class JediLanguageClientFactory implements ILanguageClientFactory { - constructor(private interpreterService: IInterpreterService) { } + constructor(private interpreterService: IInterpreterService) {} public async createLanguageClient( resource: Resource, diff --git a/extensions/positron-python/src/client/activation/jedi/languageServerProxy.ts b/extensions/positron-python/src/client/activation/jedi/languageServerProxy.ts index bd0a550407ef..d7ffe8328b9e 100644 --- a/extensions/positron-python/src/client/activation/jedi/languageServerProxy.ts +++ b/extensions/positron-python/src/client/activation/jedi/languageServerProxy.ts @@ -22,7 +22,7 @@ export class JediLanguageServerProxy implements ILanguageServerProxy { private lsVersion: string | undefined; - constructor(private readonly factory: ILanguageClientFactory) { } + constructor(private readonly factory: ILanguageClientFactory) {} private static versionTelemetryProps(instance: JediLanguageServerProxy) { return { diff --git a/extensions/positron-python/src/client/application/diagnostics/checks/pythonInterpreter.ts b/extensions/positron-python/src/client/application/diagnostics/checks/pythonInterpreter.ts index b29e32286086..58a2cfbfb73b 100644 --- a/extensions/positron-python/src/client/application/diagnostics/checks/pythonInterpreter.ts +++ b/extensions/positron-python/src/client/application/diagnostics/checks/pythonInterpreter.ts @@ -103,10 +103,8 @@ export class DefaultShellDiagnostic extends BaseDiagnostic { export const InvalidPythonInterpreterServiceId = 'InvalidPythonInterpreterServiceId'; @injectable() -export class InvalidPythonInterpreterService - extends BaseDiagnosticsService - implements IExtensionSingleActivationService -{ +export class InvalidPythonInterpreterService extends BaseDiagnosticsService + implements IExtensionSingleActivationService { public readonly supportedWorkspaceTypes = { untrustedWorkspace: false, virtualWorkspace: true }; constructor( diff --git a/extensions/positron-python/src/client/common/configSettings.ts b/extensions/positron-python/src/client/common/configSettings.ts index 910a0dcc4b0a..0363a077d057 100644 --- a/extensions/positron-python/src/client/common/configSettings.ts +++ b/extensions/positron-python/src/client/common/configSettings.ts @@ -354,15 +354,15 @@ export class PythonSettings implements IPythonSettings { this.testing = this.testing ? this.testing : { - promptToConfigure: true, - debugPort: 3000, - pytestArgs: [], - pytestEnabled: false, - pytestPath: 'pytest', - unittestArgs: [], - unittestEnabled: false, - autoTestDiscoverOnSaveEnabled: true, - }; + promptToConfigure: true, + debugPort: 3000, + pytestArgs: [], + pytestEnabled: false, + pytestPath: 'pytest', + unittestArgs: [], + unittestEnabled: false, + autoTestDiscoverOnSaveEnabled: true, + }; this.testing.pytestPath = getAbsolutePath(systemVariables.resolveAny(this.testing.pytestPath), workspaceRoot); if (this.testing.cwd) { this.testing.cwd = getAbsolutePath(systemVariables.resolveAny(this.testing.cwd), workspaceRoot); @@ -385,12 +385,12 @@ export class PythonSettings implements IPythonSettings { this.terminal = this.terminal ? this.terminal : { - executeInFileDir: true, - focusAfterLaunch: false, - launchArgs: [], - activateEnvironment: true, - activateEnvInCurrentTerminal: false, - }; + executeInFileDir: true, + focusAfterLaunch: false, + launchArgs: [], + activateEnvironment: true, + activateEnvInCurrentTerminal: false, + }; this.REPL = pythonSettings.get('REPL')!; const experiments = pythonSettings.get('experiments')!; @@ -404,10 +404,10 @@ export class PythonSettings implements IPythonSettings { this.experiments = this.experiments ? this.experiments : { - enabled: true, - optInto: [], - optOutFrom: [], - }; + enabled: true, + optInto: [], + optOutFrom: [], + }; const tensorBoardSettings = systemVariables.resolveAny( pythonSettings.get('tensorBoard'), diff --git a/extensions/positron-python/src/client/common/constants.ts b/extensions/positron-python/src/client/common/constants.ts index f2b2095a4e53..a61b1534c3bd 100644 --- a/extensions/positron-python/src/client/common/constants.ts +++ b/extensions/positron-python/src/client/common/constants.ts @@ -119,7 +119,7 @@ export function isUnitTestExecution(): boolean { export const UseProposedApi = Symbol('USE_VSC_PROPOSED_API'); // --- Start Positron --- -export const IPYKERNEL_VERSION = '>=6.19.1' +export const IPYKERNEL_VERSION = '>=6.19.1'; // --- End Positron export * from '../constants'; diff --git a/extensions/positron-python/src/client/common/terminal/shellDetectors/baseShellDetector.ts b/extensions/positron-python/src/client/common/terminal/shellDetectors/baseShellDetector.ts index a702b8f15dec..4262bdf80364 100644 --- a/extensions/positron-python/src/client/common/terminal/shellDetectors/baseShellDetector.ts +++ b/extensions/positron-python/src/client/common/terminal/shellDetectors/baseShellDetector.ts @@ -49,7 +49,7 @@ detectableShells.set(TerminalShellType.xonsh, IS_XONSH); @injectable() export abstract class BaseShellDetector implements IShellDetector { - constructor(@unmanaged() public readonly priority: number) { } + constructor(@unmanaged() public readonly priority: number) {} public abstract identify( telemetryProperties: ShellIdentificationTelemetry, terminal?: Terminal, diff --git a/extensions/positron-python/src/client/common/types.ts b/extensions/positron-python/src/client/common/types.ts index a1f4f997c7a3..cd46de110fee 100644 --- a/extensions/positron-python/src/client/common/types.ts +++ b/extensions/positron-python/src/client/common/types.ts @@ -29,11 +29,11 @@ export interface IDisposable { } export const ILogOutputChannel = Symbol('ILogOutputChannel'); -export interface ILogOutputChannel extends LogOutputChannel { } +export interface ILogOutputChannel extends LogOutputChannel {} export const ITestOutputChannel = Symbol('ITestOutputChannel'); -export interface ITestOutputChannel extends OutputChannel { } +export interface ITestOutputChannel extends OutputChannel {} export const IDocumentSymbolProvider = Symbol('IDocumentSymbolProvider'); -export interface IDocumentSymbolProvider extends DocumentSymbolProvider { } +export interface IDocumentSymbolProvider extends DocumentSymbolProvider {} export const IsWindows = Symbol('IS_WINDOWS'); export const IDisposableRegistry = Symbol('IDisposableRegistry'); export type IDisposableRegistry = IDisposable[]; @@ -282,7 +282,7 @@ export type DownloadOptions = { }; export const IExtensionContext = Symbol('ExtensionContext'); -export interface IExtensionContext extends ExtensionContext { } +export interface IExtensionContext extends ExtensionContext {} export const IExtensions = Symbol('IExtensions'); export interface IExtensions { diff --git a/extensions/positron-python/src/client/interpreter/configuration/environmentTypeComparer.ts b/extensions/positron-python/src/client/interpreter/configuration/environmentTypeComparer.ts index 516182220d28..327ee2f2ad65 100644 --- a/extensions/positron-python/src/client/interpreter/configuration/environmentTypeComparer.ts +++ b/extensions/positron-python/src/client/interpreter/configuration/environmentTypeComparer.ts @@ -136,7 +136,7 @@ export class EnvironmentTypeComparer implements IInterpreterComparer { if (pyenvVersion && i.envType === EnvironmentType.Pyenv) { // pyenvVersion may also be the name of a virtual environment, rather than a version number // Do not recommend pyenv interpreters that do not match the specified pyenv version. - return isVirtualEnvName(pyenvVersion) && i.envName === pyenvVersion + return isVirtualEnvName(pyenvVersion) && i.envName === pyenvVersion; } // --- End Positron --- return true; @@ -312,10 +312,13 @@ export function getPyenvVersion(workspacePath: string | undefined): string | und } // if the local pyenv version file does not exist in the workspace, we need to check parents of the workspace if (workspacePath) { - const parentPyenvVersion = checkParentDirs(workspacePath, '.python-version', { resolveSymlinks: true, maxDepth: 10 }); + const parentPyenvVersion = checkParentDirs(workspacePath, '.python-version', { + resolveSymlinks: true, + maxDepth: 10, + }); if (parentPyenvVersion) { return readFileSync(parentPyenvVersion).trim(); - }; + } } const globalPyenvVersion = path.join(getPyenvDir(), 'version'); diff --git a/extensions/positron-python/src/client/positron/provider.ts b/extensions/positron-python/src/client/positron/provider.ts index 74b10027e213..604482d99a1a 100644 --- a/extensions/positron-python/src/client/positron/provider.ts +++ b/extensions/positron-python/src/client/positron/provider.ts @@ -84,10 +84,8 @@ export async function* pythonRuntimeDiscoverer( // NOTE: We may need to pass a resource to getSettings to support multi-root workspaces const workspaceUri = vscode.workspace.workspaceFolders?.[0]?.uri; const suggestions = await interpreterSelector.getSuggestions(workspaceUri); - let recommendedInterpreter = interpreterSelector.getRecommendedSuggestion( - suggestions, - workspaceUri, - )?.interpreter; + let recommendedInterpreter = interpreterSelector.getRecommendedSuggestion(suggestions, workspaceUri) + ?.interpreter; if (!recommendedInterpreter) { // fallback to active interpreter if we don't have a recommended interpreter recommendedInterpreter = await interpreterService.getActiveInterpreter(workspaceUri); diff --git a/extensions/positron-python/src/client/positron/runtime.ts b/extensions/positron-python/src/client/positron/runtime.ts index 228eac6d00cb..998e30dfd3e9 100644 --- a/extensions/positron-python/src/client/positron/runtime.ts +++ b/extensions/positron-python/src/client/positron/runtime.ts @@ -56,7 +56,7 @@ export class PythonRuntime implements positron.LanguageRuntime, vscode.Disposabl private _state: positron.RuntimeState = positron.RuntimeState.Uninitialized; /** The service for getting the Python extension interpreter path */ - private _interpreterPathService: IInterpreterPathService + private _interpreterPathService: IInterpreterPathService; constructor( private readonly serviceContainer: IServiceContainer, @@ -167,8 +167,11 @@ export class PythonRuntime implements positron.LanguageRuntime, vscode.Disposabl // We require ipykernel >= 6.19.1 for the Python runtime in order to ensure the comm package // can be imported on its own (https://github.com/ipython/ipykernel/releases/tag/v6.18.0) - const hasCompatibleKernel = await this.installer.isProductVersionCompatible(Product.ipykernel, IPYKERNEL_VERSION, this.interpreter); - + const hasCompatibleKernel = await this.installer.isProductVersionCompatible( + Product.ipykernel, + IPYKERNEL_VERSION, + this.interpreter, + ); if (hasCompatibleKernel !== ProductInstallStatus.Installed) { // Pass a cancellation token to enable VSCode's progress indicator and let the user @@ -223,7 +226,7 @@ export class PythonRuntime implements positron.LanguageRuntime, vscode.Disposabl await this._installIpykernel(); // Update the active environment in the Python extension. - this._interpreterPathService.update(undefined, vscode.ConfigurationTarget.Global, this.interpreter.path) + this._interpreterPathService.update(undefined, vscode.ConfigurationTarget.Global, this.interpreter.path); this.pythonApi.environments.updateActiveEnvironmentPath(this.interpreter.path); @@ -267,25 +270,25 @@ export class PythonRuntime implements positron.LanguageRuntime, vscode.Disposabl } } - // Keep track of LSP init to avoid stopping in the middle of startup - private _lspStarting: Thenable = Promise.resolve(); + // Keep track of LSP init to avoid stopping in the middle of startup + private _lspStarting: Thenable = Promise.resolve(); async restart(): Promise { if (this._kernel) { - // Stop the LSP client before restarting the kernel. Don't stop it - // until fully started to avoid an inconsistent state where the - // deactivation request comes in between the creation of the LSP - // comm and the LSP client. - // - // A cleaner way to set this up might be to put `this._lsp` in - // charge of creating the LSP comm, then `deactivate()` could - // keep track of this state itself. - await Promise.race([ - this._lspStarting, - whenTimeout(400, () => { - this._kernel!.emitJupyterLog('LSP startup timed out during interpreter restart'); - }) - ]); + // Stop the LSP client before restarting the kernel. Don't stop it + // until fully started to avoid an inconsistent state where the + // deactivation request comes in between the creation of the LSP + // comm and the LSP client. + // + // A cleaner way to set this up might be to put `this._lsp` in + // charge of creating the LSP comm, then `deactivate()` could + // keep track of this state itself. + await Promise.race([ + this._lspStarting, + whenTimeout(400, () => { + this._kernel!.emitJupyterLog('LSP startup timed out during interpreter restart'); + }), + ]); await this._lsp.deactivate(true); return this._kernel.restart(); @@ -390,8 +393,8 @@ export class PythonRuntime implements positron.LanguageRuntime, vscode.Disposabl if (this._kernel) { const runtimeError = err as positron.RuntimeMethodError; this._kernel.emitJupyterLog( - `Error setting initial console width: ${runtimeError.message} ` + - `(${runtimeError.code})`); + `Error setting initial console width: ${runtimeError.message} (${runtimeError.code})`, + ); } } }); diff --git a/extensions/positron-python/src/client/positron/util.ts b/extensions/positron-python/src/client/positron/util.ts index 855c7b071bb3..be96b95cb79c 100644 --- a/extensions/positron-python/src/client/positron/util.ts +++ b/extensions/positron-python/src/client/positron/util.ts @@ -2,19 +2,6 @@ * Copyright (C) 2022 Posit Software, PBC. All rights reserved. *--------------------------------------------------------------------------------------------*/ -import * as vscode from 'vscode'; - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -export function withActiveExtension(ext: vscode.Extension, callback: () => void) { - - if (ext.isActive) { - callback(); - } else { - ext.activate().then(callback); - } - -} - export class PromiseHandles { resolve!: (value: T | Promise) => void; @@ -31,10 +18,10 @@ export class PromiseHandles { } export function delay(ms: number): Promise { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise((resolve) => setTimeout(resolve, ms)); } export async function whenTimeout(ms: number, fn: () => T): Promise { - await delay(ms); - return fn(); + await delay(ms); + return fn(); } diff --git a/extensions/positron-python/src/client/pythonEnvironments/common/externalDependencies.ts b/extensions/positron-python/src/client/pythonEnvironments/common/externalDependencies.ts index d2272e23dc4f..4c970e5d7f3a 100644 --- a/extensions/positron-python/src/client/pythonEnvironments/common/externalDependencies.ts +++ b/extensions/positron-python/src/client/pythonEnvironments/common/externalDependencies.ts @@ -196,9 +196,8 @@ export async function* getSubDirs( export function checkParentDirs( root: string, fileName: string, - options?: { resolveSymlinks?: boolean, maxDepth?: number }, + options?: { resolveSymlinks?: boolean; maxDepth?: number }, ): string | undefined { - let depth = 0; while (pathExistsSync(root) && (options?.maxDepth === undefined || depth < options.maxDepth)) { const filePath = path.join(root, fileName); diff --git a/extensions/positron-python/src/test/application/diagnostics/checks/pythonInterpreter.unit.test.ts b/extensions/positron-python/src/test/application/diagnostics/checks/pythonInterpreter.unit.test.ts index 348330d29bb2..fabef52efbd5 100644 --- a/extensions/positron-python/src/test/application/diagnostics/checks/pythonInterpreter.unit.test.ts +++ b/extensions/positron-python/src/test/application/diagnostics/checks/pythonInterpreter.unit.test.ts @@ -163,7 +163,7 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { interpreterService.setup((i) => i.hasInterpreters()).returns(() => Promise.resolve(true)); interpreterService .setup((i) => i.getActiveInterpreter(typemoq.It.isAny())) - .returns(() => Promise.resolve({ path: 'interpreterpath' } as unknown as PythonEnvironment)); + .returns(() => Promise.resolve(({ path: 'interpreterpath' } as unknown) as PythonEnvironment)); const result2 = await triggerFunction!(undefined); expect(result2).to.equal(true); }); @@ -374,7 +374,7 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { test('Handling comspec diagnostic should launch expected browser link', async () => { const diagnostic = new DefaultShellDiagnostic(DiagnosticCodes.InvalidComspecDiagnostic, undefined); - const cmd = {} as any as IDiagnosticCommand; + const cmd = ({} as any) as IDiagnosticCommand; let messagePrompt: MessageCommandPrompt | undefined; messageHandler .setup((i) => i.handle(typemoq.It.isValue(diagnostic), typemoq.It.isAny())) @@ -409,7 +409,7 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { test('Handling incomplete path diagnostic should launch expected browser link', async () => { const diagnostic = new DefaultShellDiagnostic(DiagnosticCodes.IncompletePathVarDiagnostic, undefined); - const cmd = {} as any as IDiagnosticCommand; + const cmd = ({} as any) as IDiagnosticCommand; let messagePrompt: MessageCommandPrompt | undefined; messageHandler .setup((i) => i.handle(typemoq.It.isValue(diagnostic), typemoq.It.isAny())) @@ -444,7 +444,7 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { test('Handling default shell error diagnostic should launch expected browser link', async () => { const diagnostic = new DefaultShellDiagnostic(DiagnosticCodes.DefaultShellErrorDiagnostic, undefined); - const cmd = {} as any as IDiagnosticCommand; + const cmd = ({} as any) as IDiagnosticCommand; let messagePrompt: MessageCommandPrompt | undefined; messageHandler .setup((i) => i.handle(typemoq.It.isValue(diagnostic), typemoq.It.isAny())) @@ -483,7 +483,7 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { undefined, workspaceService.object, ); - const cmd = {} as any as IDiagnosticCommand; + const cmd = ({} as any) as IDiagnosticCommand; let messagePrompt: MessageCommandPrompt | undefined; messageHandler .setup((i) => i.handle(typemoq.It.isValue(diagnostic), typemoq.It.isAny())) @@ -523,7 +523,7 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { undefined, workspaceService.object, ); - const cmd = {} as any as IDiagnosticCommand; + const cmd = ({} as any) as IDiagnosticCommand; let messagePrompt: MessageCommandPrompt | undefined; messageHandler .setup((i) => i.handle(typemoq.It.isValue(diagnostic), typemoq.It.isAny())) @@ -555,7 +555,7 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { }); test('Handling an empty diagnostic should not show a message nor return a command', async () => { const diagnostics: IDiagnostic[] = []; - const cmd = {} as any as IDiagnosticCommand; + const cmd = ({} as any) as IDiagnosticCommand; messageHandler .setup((i) => i.handle(typemoq.It.isAny(), typemoq.It.isAny())) @@ -585,10 +585,10 @@ suite('Application Diagnostics - Checks Python Interpreter', () => { undefined, workspaceService.object, ); - const cmd = {} as any as IDiagnosticCommand; - const diagnosticServiceMock = typemoq.Mock.ofInstance( - diagnosticService, - ) as any as typemoq.IMock; + const cmd = ({} as any) as IDiagnosticCommand; + const diagnosticServiceMock = (typemoq.Mock.ofInstance(diagnosticService) as any) as typemoq.IMock< + InvalidPythonInterpreterService + >; diagnosticServiceMock.setup((f) => f.canHandle(typemoq.It.isAny())).returns(() => Promise.resolve(false)); messageHandler diff --git a/extensions/positron-python/src/test/common/installer/productInstaller.unit.test.ts b/extensions/positron-python/src/test/common/installer/productInstaller.unit.test.ts index 646dba396857..2aff33a552e6 100644 --- a/extensions/positron-python/src/test/common/installer/productInstaller.unit.test.ts +++ b/extensions/positron-python/src/test/common/installer/productInstaller.unit.test.ts @@ -220,5 +220,4 @@ suite('DataScienceInstaller install', async () => { const result = await dataScienceInstaller.install(Product.ipykernel, testEnvironment); expect(result).to.equal(InstallerResponse.Installed, 'Should be Installed'); }); - }); diff --git a/extensions/positron-python/src/test/common/serviceRegistry.unit.test.ts b/extensions/positron-python/src/test/common/serviceRegistry.unit.test.ts index c90d0b43857e..c7c354c0bc57 100644 --- a/extensions/positron-python/src/test/common/serviceRegistry.unit.test.ts +++ b/extensions/positron-python/src/test/common/serviceRegistry.unit.test.ts @@ -128,7 +128,7 @@ suite('Common - Service Registry', () => { // --- Start Positron --- // Fix for Typescript v5 s.addSingleton( - // --- End Positron --- + // --- End Positron --- typemoq.It.isValue(mapping[0] as any), typemoq.It.is((value) => mapping[1] === value), ), diff --git a/extensions/positron-python/src/test/configuration/environmentTypeComparer.unit.test.ts b/extensions/positron-python/src/test/configuration/environmentTypeComparer.unit.test.ts index 3532b0a0d286..ccd0aa6add20 100644 --- a/extensions/positron-python/src/test/configuration/environmentTypeComparer.unit.test.ts +++ b/extensions/positron-python/src/test/configuration/environmentTypeComparer.unit.test.ts @@ -330,7 +330,7 @@ suite('getPyenvVersion tests', () => { setup(() => { const workspacePath = path.join('path', 'to', 'workspace'); - const globalPyenvDir = path.join('home', 'user', '.pyenv') + const globalPyenvDir = path.join('home', 'user', '.pyenv'); getActiveWorkspaceUriStub = sinon.stub().returns({ folderUri: { fsPath: workspacePath } }); getActiveWorkspaceNoWorkspaceUriStub = sinon.stub().returns(undefined); getInterpreterTypeDisplayNameStub = sinon.stub(); @@ -345,27 +345,15 @@ suite('getPyenvVersion tests', () => { } as unknown) as IInterpreterHelper; pathExistsSyncStub = sinon.stub(externalDependencies, 'pathExistsSync'); - pathExistsSyncStub - .withArgs('') - .returns(false); - pathExistsSyncStub - .withArgs(path.join(workspacePath, '.python-version')) - .returns(true); - pathExistsSyncStub - .withArgs(path.join(globalPyenvDir, 'version')) - .returns(true); + pathExistsSyncStub.withArgs('').returns(false); + pathExistsSyncStub.withArgs(path.join(workspacePath, '.python-version')).returns(true); + pathExistsSyncStub.withArgs(path.join(globalPyenvDir, 'version')).returns(true); readFileSyncStub = sinon.stub(externalDependencies, 'readFileSync'); - readFileSyncStub - .withArgs(path.join(workspacePath, '.python-version')) - .returns('3.10.2'); - readFileSyncStub - .withArgs(path.join(globalPyenvDir, 'version')) - .returns('my_global_pyenv'); + readFileSyncStub.withArgs(path.join(workspacePath, '.python-version')).returns('3.10.2'); + readFileSyncStub.withArgs(path.join(globalPyenvDir, 'version')).returns('my_global_pyenv'); checkParentDirsStub = sinon.stub(externalDependencies, 'checkParentDirs'); getPyenvDirStub = sinon.stub(pyenvUtils, 'getPyenvDir'); - getPyenvDirStub - .withArgs() - .returns(globalPyenvDir); + getPyenvDirStub.withArgs().returns(globalPyenvDir); }); teardown(() => { @@ -390,24 +378,31 @@ suite('getPyenvVersion tests', () => { test('getRecommended recommends the local pyenv version over global pythons and other pyenv versions', () => { const envA = { // global python - path: 'path', envType: EnvironmentType.Global, version: { major: 3, minor: 12, patch: 2, raw: '3.12.2' } + path: 'path', + envType: EnvironmentType.Global, + version: { major: 3, minor: 12, patch: 2, raw: '3.12.2' }, } as PythonEnvironment; const envB = { // pyenv version, does not match local .python-version or global pyenv - path: 'path', envType: EnvironmentType.Pyenv, version: { major: 3, minor: 11, patch: 2, raw: '3.11.2' } + path: 'path', + envType: EnvironmentType.Pyenv, + version: { major: 3, minor: 11, patch: 2, raw: '3.11.2' }, } as PythonEnvironment; const envC = { // local pyenv version for the workspace - path: 'path', envType: EnvironmentType.Pyenv, version: { major: 3, minor: 10, patch: 2, raw: '3.10.2' } + path: 'path', + envType: EnvironmentType.Pyenv, + version: { major: 3, minor: 10, patch: 2, raw: '3.10.2' }, } as PythonEnvironment; const envD = { // global pyenv version - path: 'path', envType: EnvironmentType.Pyenv, version: { major: 3, minor: 11, patch: 3, raw: '3.11.3' }, envName: 'my_global_pyenv' + path: 'path', + envType: EnvironmentType.Pyenv, + version: { major: 3, minor: 11, patch: 3, raw: '3.11.3' }, + envName: 'my_global_pyenv', } as PythonEnvironment; - const pythonEnvironments = [ - envA, envB, envC, envD - ]; + const pythonEnvironments = [envA, envB, envC, envD]; const workspacePath = path.join('path', 'to', 'workspace'); const workspace = Uri.file(workspacePath); @@ -419,24 +414,31 @@ suite('getPyenvVersion tests', () => { test('getRecommended recommends the global pyenv version over global pythons and other pyenv versions', () => { const envA = { // global python - path: 'path', envType: EnvironmentType.Global, version: { major: 3, minor: 12, patch: 2, raw: '3.12.2' } + path: 'path', + envType: EnvironmentType.Global, + version: { major: 3, minor: 12, patch: 2, raw: '3.12.2' }, } as PythonEnvironment; const envB = { // pyenv version, does not match local .python-version or global pyenv - path: 'path', envType: EnvironmentType.Pyenv, version: { major: 3, minor: 11, patch: 2, raw: '3.11.2' } + path: 'path', + envType: EnvironmentType.Pyenv, + version: { major: 3, minor: 11, patch: 2, raw: '3.11.2' }, } as PythonEnvironment; const envC = { // local pyenv version for the workspace - path: 'path', envType: EnvironmentType.Pyenv, version: { major: 3, minor: 10, patch: 2, raw: '3.10.2' } + path: 'path', + envType: EnvironmentType.Pyenv, + version: { major: 3, minor: 10, patch: 2, raw: '3.10.2' }, } as PythonEnvironment; const envD = { // global pyenv version - path: 'path', envType: EnvironmentType.Pyenv, version: { major: 3, minor: 11, patch: 3, raw: '3.11.3' }, envName: 'my_global_pyenv' + path: 'path', + envType: EnvironmentType.Pyenv, + version: { major: 3, minor: 11, patch: 3, raw: '3.11.3' }, + envName: 'my_global_pyenv', } as PythonEnvironment; - const pythonEnvironments = [ - envA, envB, envC, envD - ]; + const pythonEnvironments = [envA, envB, envC, envD]; const workspace = undefined; const expected = envD; diff --git a/extensions/positron-python/src/test/initialize.ts b/extensions/positron-python/src/test/initialize.ts index ef8269b62dd0..3937589900b0 100644 --- a/extensions/positron-python/src/test/initialize.ts +++ b/extensions/positron-python/src/test/initialize.ts @@ -50,7 +50,7 @@ export async function initialize(): Promise { initializePositron(); // --- End Positron --- - return api as any as IExtensionTestApi; + return (api as any) as IExtensionTestApi; } export async function activateExtension() { const extension = vscode.extensions.getExtension(PVSC_EXTENSION_ID_FOR_TESTS)!; diff --git a/extensions/positron-python/src/test/pythonEnvironments/common/externalDependencies.unit.test.ts b/extensions/positron-python/src/test/pythonEnvironments/common/externalDependencies.unit.test.ts index 4963e1a8f592..ded0ed0ceac4 100644 --- a/extensions/positron-python/src/test/pythonEnvironments/common/externalDependencies.unit.test.ts +++ b/extensions/positron-python/src/test/pythonEnvironments/common/externalDependencies.unit.test.ts @@ -13,21 +13,11 @@ suite('checkParentDirs tests', () => { setup(() => { pathExistsSyncStub = sinon.stub(fsapi, 'pathExistsSync'); - pathExistsSyncStub - .withArgs('home') - .returns(true); - pathExistsSyncStub - .withArgs(path.join('home', 'project')) - .returns(true); - pathExistsSyncStub - .withArgs(path.join('home', 'project', 'file')) - .returns(false); - pathExistsSyncStub - .withArgs(path.join('home', 'file')) - .returns(true); - pathExistsSyncStub - .withArgs(path.join('home','nonexistent-file')) - .returns(false); + pathExistsSyncStub.withArgs('home').returns(true); + pathExistsSyncStub.withArgs(path.join('home', 'project')).returns(true); + pathExistsSyncStub.withArgs(path.join('home', 'project', 'file')).returns(false); + pathExistsSyncStub.withArgs(path.join('home', 'file')).returns(true); + pathExistsSyncStub.withArgs(path.join('home', 'nonexistent-file')).returns(false); }); teardown(() => { @@ -40,7 +30,7 @@ suite('checkParentDirs tests', () => { const expected = path.join('home', 'file'); const actual = checkParentDirs(root, filename); assert.strictEqual(actual, expected); - }) + }); test('checkParentDirs does not find the file', () => { const root = path.join('home'); @@ -48,5 +38,5 @@ suite('checkParentDirs tests', () => { const expected = undefined; const actual = checkParentDirs(root, filename); assert.strictEqual(actual, expected); - }) + }); }); diff --git a/extensions/positron-python/src/test/terminals/serviceRegistry.unit.test.ts b/extensions/positron-python/src/test/terminals/serviceRegistry.unit.test.ts index 23e451e92a0b..403ddf4f3227 100644 --- a/extensions/positron-python/src/test/terminals/serviceRegistry.unit.test.ts +++ b/extensions/positron-python/src/test/terminals/serviceRegistry.unit.test.ts @@ -46,7 +46,7 @@ suite('Terminal - Service Registry', () => { // --- Start Positron --- // Fix for Typescript v5 s.addSingleton( - // --- End Positron --- + // --- End Positron --- typemoq.It.is((v) => args[0] === v), typemoq.It.is((value) => args[1] === value), ), @@ -58,7 +58,7 @@ suite('Terminal - Service Registry', () => { // --- Start Positron --- // Fix for Typescript v5 s.addSingleton( - // --- End Positron --- + // --- End Positron --- typemoq.It.is((v) => args[0] === v), typemoq.It.is((value) => args[1] === value), @@ -73,7 +73,7 @@ suite('Terminal - Service Registry', () => { // --- Start Positron --- // Fix for Typescript v5 s.addBinding( - // --- End Positron --- + // --- End Positron --- typemoq.It.is((v) => ITerminalEnvVarCollectionService === v), typemoq.It.is((value) => IExtensionActivationService === value), ), diff --git a/extensions/positron-python/yarn.lock b/extensions/positron-python/yarn.lock index 4eab49135be9..2ed9da0a683e 100644 --- a/extensions/positron-python/yarn.lock +++ b/extensions/positron-python/yarn.lock @@ -7234,10 +7234,10 @@ prepend-http@^2.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== -prettier@^2.0.2: - version "2.8.4" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.4.tgz#34dd2595629bfbb79d344ac4a91ff948694463c3" - integrity sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw== +prettier@2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.2.tgz#1ba8f3eb92231e769b7fcd7cb73ae1b6b74ade08" + integrity sha512-5xJQIPT8BraI7ZnaDwSbu5zLrB6vvi8hVV58yHQ+QK64qrY40dULy0HSRlQ2/2IdzeBpjhDkqdcFBnFeDEMVdg== pretty-hrtime@^1.0.0: version "1.0.3"