diff --git a/package.json b/package.json
index 716335f73767..6342e1327205 100644
--- a/package.json
+++ b/package.json
@@ -603,88 +603,6 @@
"scope": "window",
"type": "string"
},
- "python.linting.banditArgs": {
- "default": [],
- "description": "%python.linting.banditArgs.description%",
- "items": {
- "type": "string"
- },
- "scope": "resource",
- "type": "array",
- "markdownDeprecationMessage": "%python.linting.banditArgs.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.banditArgs.deprecationMessage%"
- },
- "python.linting.banditEnabled": {
- "default": false,
- "description": "%python.linting.banditEnabled.description%",
- "scope": "resource",
- "type": "boolean",
- "markdownDeprecationMessage": "%python.linting.banditArgs.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.banditArgs.deprecationMessage%"
- },
- "python.linting.banditPath": {
- "default": "bandit",
- "description": "%python.linting.banditPath.description%",
- "scope": "machine-overridable",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.banditPath.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.banditPath.deprecationMessage%"
- },
- "python.linting.cwd": {
- "default": null,
- "description": "%python.linting.cwd.description%",
- "scope": "resource",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.cwd.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.cwd.deprecationMessage%"
- },
- "python.linting.enabled": {
- "default": true,
- "description": "%python.linting.enabled.description%",
- "scope": "resource",
- "type": "boolean",
- "markdownDeprecationMessage": "%python.linting.enabled.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.enabled.deprecationMessage%"
- },
- "python.linting.flake8Args": {
- "default": [],
- "description": "%python.linting.flake8Args.description%",
- "items": {
- "type": "string"
- },
- "scope": "resource",
- "type": "array",
- "markdownDeprecationMessage": "%python.linting.flake8Args.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.flake8Args.deprecationMessage%"
- },
- "python.linting.flake8CategorySeverity.E": {
- "default": "Error",
- "description": "%python.linting.flake8CategorySeverity.E.description%",
- "enum": [
- "Error",
- "Hint",
- "Information",
- "Warning"
- ],
- "scope": "resource",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.flake8CategorySeverity.E.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.flake8CategorySeverity.E.deprecationMessage%"
- },
- "python.linting.flake8CategorySeverity.F": {
- "default": "Error",
- "description": "%python.linting.flake8CategorySeverity.F.description%",
- "enum": [
- "Error",
- "Hint",
- "Information",
- "Warning"
- ],
- "scope": "resource",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.flake8CategorySeverity.F.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.flake8CategorySeverity.F.deprecationMessage%"
- },
"python.interpreter.infoVisibility": {
"default": "onPythonRelated",
"description": "%python.interpreter.infoVisibility.description%",
@@ -701,360 +619,6 @@
"scope": "machine",
"type": "string"
},
- "python.linting.flake8CategorySeverity.W": {
- "default": "Warning",
- "description": "%python.linting.flake8CategorySeverity.W.description%",
- "enum": [
- "Error",
- "Hint",
- "Information",
- "Warning"
- ],
- "scope": "resource",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.flake8CategorySeverity.W.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.flake8CategorySeverity.W.deprecationMessage%"
- },
- "python.linting.flake8Enabled": {
- "default": false,
- "description": "%python.linting.flake8Enabled.description%",
- "scope": "resource",
- "type": "boolean",
- "markdownDeprecationMessage": "%python.linting.flake8Enabled.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.flake8Enabled.deprecationMessage%"
- },
- "python.linting.flake8Path": {
- "default": "flake8",
- "description": "%python.linting.flake8Path.description%",
- "scope": "machine-overridable",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.flake8Path.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.flake8Path.deprecationMessage%"
- },
- "python.linting.ignorePatterns": {
- "default": [
- "**/site-packages/**/*.py",
- ".vscode/*.py"
- ],
- "description": "%python.linting.ignorePatterns.description%",
- "items": {
- "type": "string"
- },
- "scope": "resource",
- "type": "array",
- "uniqueItems": true,
- "markdownDeprecationMessage": "%python.linting.ignorePatterns.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.ignorePatterns.deprecationMessage%"
- },
- "python.linting.lintOnSave": {
- "default": true,
- "description": "%python.linting.lintOnSave.description%",
- "scope": "resource",
- "type": "boolean",
- "markdownDeprecationMessage": "%python.linting.lintOnSave.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.lintOnSave.deprecationMessage%"
- },
- "python.linting.maxNumberOfProblems": {
- "default": 100,
- "description": "%python.linting.maxNumberOfProblems.description%",
- "scope": "resource",
- "type": "number",
- "markdownDeprecationMessage": "%python.linting.maxNumberOfProblems.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.maxNumberOfProblems.deprecationMessage%"
- },
- "python.linting.mypyArgs": {
- "default": [
- "--follow-imports=silent",
- "--ignore-missing-imports",
- "--show-column-numbers",
- "--no-pretty"
- ],
- "description": "%python.linting.mypyArgs.description%",
- "items": {
- "type": "string"
- },
- "scope": "resource",
- "type": "array",
- "markdownDeprecationMessage": "%python.linting.mypyArgs.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.mypyArgs.deprecationMessage%"
- },
- "python.linting.mypyCategorySeverity.error": {
- "default": "Error",
- "description": "%python.linting.mypyCategorySeverity.error.description%",
- "enum": [
- "Error",
- "Hint",
- "Information",
- "Warning"
- ],
- "scope": "resource",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.mypyCategorySeverity.error.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.mypyCategorySeverity.error.deprecationMessage%"
- },
- "python.linting.mypyCategorySeverity.note": {
- "default": "Information",
- "description": "%python.linting.mypyCategorySeverity.note.description%",
- "enum": [
- "Error",
- "Hint",
- "Information",
- "Warning"
- ],
- "scope": "resource",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.mypyCategorySeverity.note.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.mypyCategorySeverity.note.deprecationMessage%"
- },
- "python.linting.mypyEnabled": {
- "default": false,
- "description": "%python.linting.mypyEnabled.description%",
- "scope": "resource",
- "type": "boolean",
- "markdownDeprecationMessage": "%python.linting.mypyEnabled.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.mypyEnabled.deprecationMessage%"
- },
- "python.linting.mypyPath": {
- "default": "mypy",
- "description": "%python.linting.mypyPath.description%",
- "scope": "machine-overridable",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.mypyPath.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.mypyPath.deprecationMessage%"
- },
- "python.linting.prospectorArgs": {
- "default": [],
- "description": "%python.linting.prospectorArgs.description%",
- "items": {
- "type": "string"
- },
- "scope": "resource",
- "type": "array",
- "markdownDeprecationMessage": "%python.linting.prospectorArgs.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.prospectorArgs.deprecationMessage%"
- },
- "python.linting.prospectorEnabled": {
- "default": false,
- "description": "%python.linting.prospectorEnabled.description%",
- "scope": "resource",
- "type": "boolean",
- "markdownDeprecationMessage": "%python.linting.prospectorEnabled.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.prospectorEnabled.deprecationMessage%"
- },
- "python.linting.prospectorPath": {
- "default": "prospector",
- "description": "%python.linting.prospectorPath.description%",
- "scope": "machine-overridable",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.prospectorPath.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.prospectorPath.deprecationMessage%"
- },
- "python.linting.pycodestyleArgs": {
- "default": [],
- "description": "%python.linting.pycodestyleArgs.description%",
- "items": {
- "type": "string"
- },
- "scope": "resource",
- "type": "array",
- "markdownDeprecationMessage": "%python.linting.pycodestyleArgs.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pycodestyleArgs.deprecationMessage%"
- },
- "python.linting.pycodestyleCategorySeverity.E": {
- "default": "Error",
- "description": "%python.linting.pycodestyleCategorySeverity.E.description%",
- "enum": [
- "Error",
- "Hint",
- "Information",
- "Warning"
- ],
- "scope": "resource",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.pycodestyleCategorySeverity.E.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pycodestyleCategorySeverity.E.deprecationMessage%"
- },
- "python.linting.pycodestyleCategorySeverity.W": {
- "default": "Warning",
- "description": "%python.linting.pycodestyleCategorySeverity.W.description%",
- "enum": [
- "Error",
- "Hint",
- "Information",
- "Warning"
- ],
- "scope": "resource",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.pycodestyleCategorySeverity.W.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pycodestyleCategorySeverity.W.deprecationMessage%"
- },
- "python.linting.pycodestyleEnabled": {
- "default": false,
- "description": "%python.linting.pycodestyleEnabled.description%",
- "scope": "resource",
- "type": "boolean",
- "markdownDeprecationMessage": "%python.linting.pycodestyleEnabled.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pycodestyleEnabled.deprecationMessage%"
- },
- "python.linting.pycodestylePath": {
- "default": "pycodestyle",
- "description": "%python.linting.pycodestylePath.description%",
- "scope": "machine-overridable",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.pycodestylePath.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pycodestylePath.deprecationMessage%"
- },
- "python.linting.pydocstyleArgs": {
- "default": [],
- "description": "%python.linting.pydocstyleArgs.description%",
- "items": {
- "type": "string"
- },
- "scope": "resource",
- "type": "array",
- "markdownDeprecationMessage": "%python.linting.pydocstyleArgs.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pydocstyleArgs.deprecationMessage%"
- },
- "python.linting.pydocstyleEnabled": {
- "default": false,
- "description": "%python.linting.pydocstyleEnabled.description%",
- "scope": "resource",
- "type": "boolean",
- "markdownDeprecationMessage": "%python.linting.pydocstyleEnabled.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pydocstyleEnabled.deprecationMessage%"
- },
- "python.linting.pydocstylePath": {
- "default": "pydocstyle",
- "description": "%python.linting.pydocstylePath.description%",
- "scope": "machine-overridable",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.pydocstylePath.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pydocstylePath.deprecationMessage%"
- },
- "python.linting.pylamaArgs": {
- "default": [],
- "description": "%python.linting.pylamaArgs.description%",
- "items": {
- "type": "string"
- },
- "scope": "resource",
- "type": "array",
- "markdownDeprecationMessage": "%python.linting.pylamaArgs.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pylamaArgs.deprecationMessage%"
- },
- "python.linting.pylamaEnabled": {
- "default": false,
- "description": "%python.linting.pylamaEnabled.description%",
- "scope": "resource",
- "type": "boolean",
- "markdownDeprecationMessage": "%python.linting.pylamaEnabled.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pylamaEnabled.deprecationMessage%"
- },
- "python.linting.pylamaPath": {
- "default": "pylama",
- "description": "%python.linting.pylamaPath.description%",
- "scope": "machine-overridable",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.pylamaPath.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pylamaPath.deprecationMessage%"
- },
- "python.linting.pylintArgs": {
- "default": [],
- "description": "%python.linting.pylintArgs.description%",
- "items": {
- "type": "string"
- },
- "scope": "resource",
- "type": "array",
- "markdownDeprecationMessage": "%python.linting.pylintArgs.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pylintArgs.deprecationMessage%"
- },
- "python.linting.pylintCategorySeverity.convention": {
- "default": "Information",
- "description": "%python.linting.pylintCategorySeverity.convention.description%",
- "enum": [
- "Error",
- "Hint",
- "Information",
- "Warning"
- ],
- "scope": "resource",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.pylintCategorySeverity.convention.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pylintCategorySeverity.convention.deprecationMessage%"
- },
- "python.linting.pylintCategorySeverity.error": {
- "default": "Error",
- "description": "%python.linting.pylintCategorySeverity.error.description%",
- "enum": [
- "Error",
- "Hint",
- "Information",
- "Warning"
- ],
- "scope": "resource",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.pylintCategorySeverity.error.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pylintCategorySeverity.error.deprecationMessage%"
- },
- "python.linting.pylintCategorySeverity.fatal": {
- "default": "Error",
- "description": "%python.linting.pylintCategorySeverity.fatal.description%",
- "enum": [
- "Error",
- "Hint",
- "Information",
- "Warning"
- ],
- "scope": "resource",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.pylintCategorySeverity.fatal.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pylintCategorySeverity.fatal.deprecationMessage%"
- },
- "python.linting.pylintCategorySeverity.refactor": {
- "default": "Hint",
- "description": "%python.linting.pylintCategorySeverity.refactor.description%",
- "enum": [
- "Error",
- "Hint",
- "Information",
- "Warning"
- ],
- "scope": "resource",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.pylintCategorySeverity.refactor.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pylintCategorySeverity.refactor.deprecationMessage%"
- },
- "python.linting.pylintCategorySeverity.warning": {
- "default": "Warning",
- "description": "%python.linting.pylintCategorySeverity.warning.description%",
- "enum": [
- "Error",
- "Hint",
- "Information",
- "Warning"
- ],
- "scope": "resource",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.pylintCategorySeverity.warning.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pylintCategorySeverity.warning.deprecationMessage%"
- },
- "python.linting.pylintEnabled": {
- "default": false,
- "description": "%python.linting.pylintEnabled.description%",
- "scope": "resource",
- "type": "boolean",
- "markdownDeprecationMessage": "%python.linting.pylintEnabled.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pylintEnabled.deprecationMessage%"
- },
- "python.linting.pylintPath": {
- "default": "pylint",
- "description": "%python.linting.pylintPath.description%",
- "scope": "machine-overridable",
- "type": "string",
- "markdownDeprecationMessage": "%python.linting.pylintPath.markdownDeprecationMessage%",
- "deprecationMessage": "%python.linting.pylintPath.deprecationMessage%"
- },
"python.logging.level": {
"default": "error",
"deprecationMessage": "%python.logging.level.deprecation%",
diff --git a/package.nls.json b/package.nls.json
index c738b3692daf..f328ee613ba9 100644
--- a/package.nls.json
+++ b/package.nls.json
@@ -49,133 +49,10 @@
"python.languageServer.jediDescription": "Use Jedi behind the Language Server Protocol (LSP) as a language server.",
"python.languageServer.pylanceDescription": "Use Pylance as a language server.",
"python.languageServer.noneDescription": "Disable language server capabilities.",
- "python.linting.banditArgs.description": "Arguments passed in. Each argument is a separate item in the array.",
- "python.linting.banditArgs.markdownDeprecationMessage": "Bandit support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.banditArgs.deprecationMessage": "Bandit support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.banditEnabled.description": "Whether to lint Python files using bandit.",
- "python.linting.banditEnabled.markdownDeprecationMessage": "Bandit support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.banditEnabled.deprecationMessage": "Bandit support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.banditPath.description": "Path to bandit, you can use a custom version of bandit by modifying this setting to include the full path.",
- "python.linting.banditPath.markdownDeprecationMessage": "Bandit support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.banditPath.deprecationMessage": "Bandit support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.cwd.description": "Optional working directory for linters.",
- "python.linting.cwd.markdownDeprecationMessage": "This setting will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.cwd.deprecationMessage": "This setting will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.enabled.description": "Whether to lint Python files.",
- "python.linting.enabled.markdownDeprecationMessage": "This setting will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.enabled.deprecationMessage": "This setting will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.flake8Args.description": "Arguments passed in. Each argument is a separate item in the array.",
- "python.linting.flake8Args.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Flake8 extension](https://marketplace.visualstudio.com/items?itemName=ms-python.flake8).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.flake8Args.deprecationMessage": "This setting will soon be deprecated. Please use the Flake8 extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.flake8CategorySeverity.E.description": "Severity of Flake8 message type 'E'.",
- "python.linting.flake8CategorySeverity.E.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Flake8 extension](https://marketplace.visualstudio.com/items?itemName=ms-python.flake8).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.flake8CategorySeverity.E.deprecationMessage": "This setting will soon be deprecated. Please use the Flake8 extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.flake8CategorySeverity.F.description": "Severity of Flake8 message type 'F'.",
- "python.linting.flake8CategorySeverity.F.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Flake8 extension](https://marketplace.visualstudio.com/items?itemName=ms-python.flake8).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.flake8CategorySeverity.F.deprecationMessage": "This setting will soon be deprecated. Please use the Flake8 extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.flake8CategorySeverity.W.description": "Severity of Flake8 message type 'W'.",
- "python.linting.flake8CategorySeverity.W.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Flake8 extension](https://marketplace.visualstudio.com/items?itemName=ms-python.flake8).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.flake8CategorySeverity.W.deprecationMessage": "This setting will soon be deprecated. Please use the Flake8 extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.flake8Enabled.description": "Whether to lint Python files using flake8.",
- "python.linting.flake8Enabled.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Flake8 extension](https://marketplace.visualstudio.com/items?itemName=ms-python.flake8).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.flake8Enabled.deprecationMessage": "This setting will soon be deprecated. Please use the Flake8 extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.flake8Path.description": "Path to flake8, you can use a custom version of flake8 by modifying this setting to include the full path.",
- "python.linting.flake8Path.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Flake8 extension](https://marketplace.visualstudio.com/items?itemName=ms-python.flake8).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.flake8Path.deprecationMessage": "This setting will soon be deprecated. Please use the Flake8 extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.ignorePatterns.description": "Patterns used to exclude files or folders from being linted.",
- "python.linting.ignorePatterns.markdownDeprecationMessage": "This setting will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.ignorePatterns.deprecationMessage": "This setting will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
"python.interpreter.infoVisibility.description": "Controls when to display information of selected interpreter in the status bar.",
"python.interpreter.infoVisibility.never.description": "Never display information.",
"python.interpreter.infoVisibility.onPythonRelated.description": "Only display information if Python-related files are opened.",
"python.interpreter.infoVisibility.always.description": "Always display information.",
- "python.linting.lintOnSave.description": "Whether to lint Python files when saved.",
- "python.linting.lintOnSave.markdownDeprecationMessage": "This setting will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.lintOnSave.deprecationMessage": "This setting will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.maxNumberOfProblems.description": "Controls the maximum number of problems produced by the server.",
- "python.linting.maxNumberOfProblems.markdownDeprecationMessage": "This setting will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.maxNumberOfProblems.deprecationMessage": "This setting will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.mypyArgs.description": "Arguments passed in. Each argument is a separate item in the array.",
- "python.linting.mypyArgs.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Mypy Type Checker extension](https://marketplace.visualstudio.com/items?itemName=ms-python.mypy-type-checker).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.mypyArgs.deprecationMessage": "This setting will soon be deprecated. Please use the Mypy Type Checker extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.mypyCategorySeverity.error.description": "Severity of Mypy message type 'Error'.",
- "python.linting.mypyCategorySeverity.error.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Mypy Type Checker extension](https://marketplace.visualstudio.com/items?itemName=ms-python.mypy-type-checker).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.mypyCategorySeverity.error.deprecationMessage": "This setting will soon be deprecated. Please use the Mypy Type Checker extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.mypyCategorySeverity.note.description": "Severity of Mypy message type 'Note'.",
- "python.linting.mypyCategorySeverity.note.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Mypy Type Checker extension](https://marketplace.visualstudio.com/items?itemName=ms-python.mypy-type-checker).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.mypyCategorySeverity.note.deprecationMessage": "This setting will soon be deprecated. Please use the Mypy Type Checker extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.mypyEnabled.description": "Whether to lint Python files using mypy.",
- "python.linting.mypyEnabled.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Mypy Type Checker extension](https://marketplace.visualstudio.com/items?itemName=ms-python.mypy-type-checker).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.mypyEnabled.deprecationMessage": "This setting will soon be deprecated. Please use the Mypy Type Checker extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.mypyPath.description": "Path to mypy, you can use a custom version of mypy by modifying this setting to include the full path.",
- "python.linting.mypyPath.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Mypy Type Checker extension](https://marketplace.visualstudio.com/items?itemName=ms-python.mypy-type-checker).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.mypyPath.deprecationMessage": "This setting will soon be deprecated. Please use the Mypy Type Checker extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.prospectorArgs.description": "Arguments passed in. Each argument is a separate item in the array.",
- "python.linting.prospectorArgs.markdownDeprecationMessage": "Prospector support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.prospectorArgs.deprecationMessage": "Prospector support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.prospectorEnabled.description": "Whether to lint Python files using prospector.",
- "python.linting.prospectorEnabled.markdownDeprecationMessage": "Prospector support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.prospectorEnabled.deprecationMessage": "Prospector support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.prospectorPath.description": "Path to Prospector, you can use a custom version of prospector by modifying this setting to include the full path.",
- "python.linting.prospectorPath.markdownDeprecationMessage": "Prospector support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.prospectorPath.deprecationMessage": "Prospector support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pycodestyleArgs.description": "Arguments passed in. Each argument is a separate item in the array.",
- "python.linting.pycodestyleArgs.markdownDeprecationMessage": "Pycodestyle support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pycodestyleArgs.deprecationMessage": "Pycodestyle support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pycodestyleCategorySeverity.E.description": "Severity of pycodestyle message type 'E'.",
- "python.linting.pycodestyleCategorySeverity.E.markdownDeprecationMessage": "Pycodestyle support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pycodestyleCategorySeverity.E.deprecationMessage": "Pycodestyle support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pycodestyleCategorySeverity.W.description": "Severity of pycodestyle message type 'W'.",
- "python.linting.pycodestyleCategorySeverity.W.markdownDeprecationMessage": "Pycodestyle support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pycodestyleCategorySeverity.W.deprecationMessage": "Pycodestyle support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pycodestyleEnabled.description": "Whether to lint Python files using pycodestyle.",
- "python.linting.pycodestyleEnabled.markdownDeprecationMessage": "Pycodestyle support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pycodestyleEnabled.deprecationMessage": "Pycodestyle support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pycodestylePath.description": "Path to pycodestyle, you can use a custom version of pycodestyle by modifying this setting to include the full path.",
- "python.linting.pycodestylePath.markdownDeprecationMessage": "Pycodestyle support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pycodestylePath.deprecationMessage": "Pycodestyle support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pydocstyleArgs.description": "Arguments passed in. Each argument is a separate item in the array.",
- "python.linting.pydocstyleArgs.markdownDeprecationMessage": "Pydocstyle support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pydocstyleArgs.deprecationMessage": "Pydocstyle support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pydocstyleEnabled.description": "Whether to lint Python files using pydocstyle.",
- "python.linting.pydocstyleEnabled.markdownDeprecationMessage": "Pydocstyle support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pydocstyleEnabled.deprecationMessage": "Pydocstyle support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pydocstylePath.description": "Path to pydocstyle, you can use a custom version of pydocstyle by modifying this setting to include the full path.",
- "python.linting.pydocstylePath.markdownDeprecationMessage": "Pydocstyle support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pydocstylePath.deprecationMessage": "Pydocstyle support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pylamaArgs.description": "Arguments passed in. Each argument is a separate item in the array.",
- "python.linting.pylamaArgs.markdownDeprecationMessage": "Pylama support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pylamaArgs.deprecationMessage": "Pylama support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pylamaEnabled.description": "Whether to lint Python files using pylama.",
- "python.linting.pylamaEnabled.markdownDeprecationMessage": "Pylama support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pylamaEnabled.deprecationMessage": "Pylama support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pylamaPath.description": "Path to pylama, you can use a custom version of pylama by modifying this setting to include the full path.",
- "python.linting.pylamaPath.markdownDeprecationMessage": "Pylama support will soon be deprecated. Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pylamaPath.deprecationMessage": "Pylama support will soon be deprecated. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pylintArgs.description": "Arguments passed in. Each argument is a separate item in the array.",
- "python.linting.pylintArgs.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Pylint extension](https://marketplace.visualstudio.com/items?itemName=ms-python.pylint).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pylintArgs.deprecationMessage": "This setting will soon be deprecated. Please use the Pylint extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pylintCategorySeverity.convention.description": "Severity of Pylint message type 'Convention/C'.",
- "python.linting.pylintCategorySeverity.convention.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Pylint extension](https://marketplace.visualstudio.com/items?itemName=ms-python.pylint).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pylintCategorySeverity.convention.deprecationMessage": "This setting will soon be deprecated. Please use the Pylint extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pylintCategorySeverity.error.description": "Severity of Pylint message type 'Error/E'.",
- "python.linting.pylintCategorySeverity.error.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Pylint extension](https://marketplace.visualstudio.com/items?itemName=ms-python.pylint).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pylintCategorySeverity.error.deprecationMessage": "This setting will soon be deprecated. Please use the Pylint extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pylintCategorySeverity.fatal.description": "Severity of Pylint message type 'Error/F'.",
- "python.linting.pylintCategorySeverity.fatal.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Pylint extension](https://marketplace.visualstudio.com/items?itemName=ms-python.pylint).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pylintCategorySeverity.fatal.deprecationMessage": "This setting will soon be deprecated. Please use the Pylint extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pylintCategorySeverity.refactor.description": "Severity of Pylint message type 'Refactor/R'.",
- "python.linting.pylintCategorySeverity.refactor.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Pylint extension](https://marketplace.visualstudio.com/items?itemName=ms-python.pylint).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pylintCategorySeverity.refactor.deprecationMessage": "This setting will soon be deprecated. Please use the Pylint extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pylintCategorySeverity.warning.description": "Severity of Pylint message type 'Warning/W'.",
- "python.linting.pylintCategorySeverity.warning.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Pylint extension](https://marketplace.visualstudio.com/items?itemName=ms-python.pylint).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pylintCategorySeverity.warning.deprecationMessage": "This setting will soon be deprecated. Please use the Pylint extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pylintEnabled.description": "Whether to lint Python files using pylint.",
- "python.linting.pylintEnabled.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Pylint extension](https://marketplace.visualstudio.com/items?itemName=ms-python.pylint).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pylintEnabled.deprecationMessage": "This setting will soon be deprecated. Please use the Pylint extension. Learn more here: https://aka.ms/AAlgvkb.",
- "python.linting.pylintPath.description": "Path to Pylint, you can use a custom version of pylint by modifying this setting to include the full path.",
- "python.linting.pylintPath.markdownDeprecationMessage": "This setting will soon be deprecated. Please use the [Pylint extension](https://marketplace.visualstudio.com/items?itemName=ms-python.pylint).
Learn more [here](https://aka.ms/AAlgvkb).",
- "python.linting.pylintPath.deprecationMessage": "This setting will soon be deprecated. Please use the Pylint extension. Learn more here: https://aka.ms/AAlgvkb.",
"python.logging.level.description": "The logging level the extension logs at, defaults to 'error'",
"python.logging.level.deprecation": "This setting is deprecated. Please use command `Developer: Set Log Level...` to set logging level.",
"python.missingPackage.severity.description": "Set severity of missing packages in requirements.txt or pyproject.toml",
diff --git a/src/client/common/configSettings.ts b/src/client/common/configSettings.ts
index cadc1515f7e6..f9c56d4992fe 100644
--- a/src/client/common/configSettings.ts
+++ b/src/client/common/configSettings.ts
@@ -6,7 +6,6 @@ import * as fs from 'fs';
import {
ConfigurationChangeEvent,
ConfigurationTarget,
- DiagnosticSeverity,
Disposable,
Event,
EventEmitter,
@@ -29,7 +28,6 @@ import {
IExperiments,
IInterpreterPathService,
IInterpreterSettings,
- ILintingSettings,
IPythonSettings,
ITensorBoardSettings,
ITerminalSettings,
@@ -106,8 +104,6 @@ export class PythonSettings implements IPythonSettings {
public devOptions: string[] = [];
- public linting!: ILintingSettings;
-
public autoComplete!: IAutoCompleteSettings;
public tensorBoard: ITensorBoardSettings | undefined;
@@ -304,94 +300,8 @@ export class PythonSettings implements IPythonSettings {
this.devOptions = systemVariables.resolveAny(pythonSettings.get('devOptions'))!;
this.devOptions = Array.isArray(this.devOptions) ? this.devOptions : [];
- const lintingSettings = systemVariables.resolveAny(pythonSettings.get('linting'))!;
- if (this.linting) {
- Object.assign(this.linting, lintingSettings);
- } else {
- this.linting = lintingSettings;
- }
-
this.globalModuleInstallation = pythonSettings.get('globalModuleInstallation') === true;
- // Support for travis.
- this.linting = this.linting
- ? this.linting
- : {
- enabled: false,
- cwd: undefined,
- ignorePatterns: [],
- flake8Args: [],
- flake8Enabled: false,
- flake8Path: 'flake8',
- lintOnSave: false,
- maxNumberOfProblems: 100,
- mypyArgs: [],
- mypyEnabled: false,
- mypyPath: 'mypy',
- banditArgs: [],
- banditEnabled: false,
- banditPath: 'bandit',
- pycodestyleArgs: [],
- pycodestyleEnabled: false,
- pycodestylePath: 'pycodestyle',
- pylamaArgs: [],
- pylamaEnabled: false,
- pylamaPath: 'pylama',
- prospectorArgs: [],
- prospectorEnabled: false,
- prospectorPath: 'prospector',
- pydocstyleArgs: [],
- pydocstyleEnabled: false,
- pydocstylePath: 'pydocstyle',
- pylintArgs: [],
- pylintEnabled: false,
- pylintPath: 'pylint',
- pylintCategorySeverity: {
- convention: DiagnosticSeverity.Hint,
- error: DiagnosticSeverity.Error,
- fatal: DiagnosticSeverity.Error,
- refactor: DiagnosticSeverity.Hint,
- warning: DiagnosticSeverity.Warning,
- },
- pycodestyleCategorySeverity: {
- E: DiagnosticSeverity.Error,
- W: DiagnosticSeverity.Warning,
- },
- flake8CategorySeverity: {
- E: DiagnosticSeverity.Error,
- W: DiagnosticSeverity.Warning,
- // Per http://flake8.pycqa.org/en/latest/glossary.html#term-error-code
- // 'F' does not mean 'fatal as in PyLint but rather 'pyflakes' such as
- // unused imports, variables, etc.
- F: DiagnosticSeverity.Warning,
- },
- mypyCategorySeverity: {
- error: DiagnosticSeverity.Error,
- note: DiagnosticSeverity.Hint,
- },
- };
- this.linting.pylintPath = getAbsolutePath(systemVariables.resolveAny(this.linting.pylintPath), workspaceRoot);
- this.linting.flake8Path = getAbsolutePath(systemVariables.resolveAny(this.linting.flake8Path), workspaceRoot);
- this.linting.pycodestylePath = getAbsolutePath(
- systemVariables.resolveAny(this.linting.pycodestylePath),
- workspaceRoot,
- );
- this.linting.pylamaPath = getAbsolutePath(systemVariables.resolveAny(this.linting.pylamaPath), workspaceRoot);
- this.linting.prospectorPath = getAbsolutePath(
- systemVariables.resolveAny(this.linting.prospectorPath),
- workspaceRoot,
- );
- this.linting.pydocstylePath = getAbsolutePath(
- systemVariables.resolveAny(this.linting.pydocstylePath),
- workspaceRoot,
- );
- this.linting.mypyPath = getAbsolutePath(systemVariables.resolveAny(this.linting.mypyPath), workspaceRoot);
- this.linting.banditPath = getAbsolutePath(systemVariables.resolveAny(this.linting.banditPath), workspaceRoot);
-
- if (this.linting.cwd) {
- this.linting.cwd = getAbsolutePath(systemVariables.resolveAny(this.linting.cwd), workspaceRoot);
- }
-
const testSettings = systemVariables.resolveAny(pythonSettings.get('testing'))!;
if (this.testing) {
Object.assign(this.testing, testSettings);
diff --git a/src/client/common/installer/moduleInstaller.ts b/src/client/common/installer/moduleInstaller.ts
index 5a4f245900ea..4cc4cd0c6a2f 100644
--- a/src/client/common/installer/moduleInstaller.ts
+++ b/src/client/common/installer/moduleInstaller.ts
@@ -238,26 +238,10 @@ export abstract class ModuleInstaller implements IModuleInstaller {
export function translateProductToModule(product: Product): string {
switch (product) {
- case Product.mypy:
- return 'mypy';
- case Product.pylama:
- return 'pylama';
- case Product.prospector:
- return 'prospector';
- case Product.pylint:
- return 'pylint';
case Product.pytest:
return 'pytest';
- case Product.pycodestyle:
- return 'pycodestyle';
- case Product.pydocstyle:
- return 'pydocstyle';
- case Product.flake8:
- return 'flake8';
case Product.unittest:
return 'unittest';
- case Product.bandit:
- return 'bandit';
case Product.tensorboard:
return 'tensorboard';
case Product.torchProfilerInstallName:
diff --git a/src/client/common/installer/productNames.ts b/src/client/common/installer/productNames.ts
index 9b917d2f1d76..00b19ce77ac3 100644
--- a/src/client/common/installer/productNames.ts
+++ b/src/client/common/installer/productNames.ts
@@ -4,14 +4,6 @@
import { Product } from '../types';
export const ProductNames = new Map();
-ProductNames.set(Product.bandit, 'bandit');
-ProductNames.set(Product.flake8, 'flake8');
-ProductNames.set(Product.mypy, 'mypy');
-ProductNames.set(Product.pycodestyle, 'pycodestyle');
-ProductNames.set(Product.pylama, 'pylama');
-ProductNames.set(Product.prospector, 'prospector');
-ProductNames.set(Product.pydocstyle, 'pydocstyle');
-ProductNames.set(Product.pylint, 'pylint');
ProductNames.set(Product.pytest, 'pytest');
ProductNames.set(Product.tensorboard, 'tensorboard');
ProductNames.set(Product.torchProfilerInstallName, 'torch-tb-profiler');
diff --git a/src/client/common/installer/productPath.ts b/src/client/common/installer/productPath.ts
index 3b3f1d7c1794..b06e4b7a48a9 100644
--- a/src/client/common/installer/productPath.ts
+++ b/src/client/common/installer/productPath.ts
@@ -7,7 +7,6 @@ import { inject, injectable } from 'inversify';
import * as path from 'path';
import { Uri } from 'vscode';
import { IServiceContainer } from '../../ioc/types';
-import { ILinterManager } from '../../linters/types';
import { ITestingService } from '../../testing/types';
import { IConfigurationService, IInstaller, Product } from '../types';
import { IProductPathService } from './types';
@@ -36,17 +35,6 @@ export abstract class BaseProductPathsService implements IProductPathService {
}
}
-@injectable()
-export class LinterProductPathService extends BaseProductPathsService {
- constructor(@inject(IServiceContainer) serviceContainer: IServiceContainer) {
- super(serviceContainer);
- }
- public getExecutableNameFromSettings(product: Product, resource?: Uri): string {
- const linterManager = this.serviceContainer.get(ILinterManager);
- return linterManager.getLinterInfo(product).pathName(resource);
- }
-}
-
@injectable()
export class TestFrameworkProductPathService extends BaseProductPathsService {
constructor(@inject(IServiceContainer) serviceContainer: IServiceContainer) {
diff --git a/src/client/common/installer/productService.ts b/src/client/common/installer/productService.ts
index af2192755fe8..bf5597cc5859 100644
--- a/src/client/common/installer/productService.ts
+++ b/src/client/common/installer/productService.ts
@@ -12,14 +12,6 @@ export class ProductService implements IProductService {
private ProductTypes = new Map();
constructor() {
- this.ProductTypes.set(Product.bandit, ProductType.Linter);
- this.ProductTypes.set(Product.flake8, ProductType.Linter);
- this.ProductTypes.set(Product.mypy, ProductType.Linter);
- this.ProductTypes.set(Product.pycodestyle, ProductType.Linter);
- this.ProductTypes.set(Product.prospector, ProductType.Linter);
- this.ProductTypes.set(Product.pydocstyle, ProductType.Linter);
- this.ProductTypes.set(Product.pylama, ProductType.Linter);
- this.ProductTypes.set(Product.pylint, ProductType.Linter);
this.ProductTypes.set(Product.pytest, ProductType.TestFramework);
this.ProductTypes.set(Product.unittest, ProductType.TestFramework);
this.ProductTypes.set(Product.tensorboard, ProductType.DataScience);
diff --git a/src/client/common/installer/serviceRegistry.ts b/src/client/common/installer/serviceRegistry.ts
index c4e7c1a089c6..d4d8a05c3a49 100644
--- a/src/client/common/installer/serviceRegistry.ts
+++ b/src/client/common/installer/serviceRegistry.ts
@@ -9,11 +9,7 @@ import { CondaInstaller } from './condaInstaller';
import { PipEnvInstaller } from './pipEnvInstaller';
import { PipInstaller } from './pipInstaller';
import { PoetryInstaller } from './poetryInstaller';
-import {
- DataScienceProductPathService,
- LinterProductPathService,
- TestFrameworkProductPathService,
-} from './productPath';
+import { DataScienceProductPathService, TestFrameworkProductPathService } from './productPath';
import { ProductService } from './productService';
import { IInstallationChannelManager, IModuleInstaller, IProductPathService, IProductService } from './types';
@@ -24,7 +20,6 @@ export function registerTypes(serviceManager: IServiceManager) {
serviceManager.addSingleton(IModuleInstaller, PoetryInstaller);
serviceManager.addSingleton(IInstallationChannelManager, InstallationChannelManager);
serviceManager.addSingleton(IProductService, ProductService);
- serviceManager.addSingleton(IProductPathService, LinterProductPathService, ProductType.Linter);
serviceManager.addSingleton(
IProductPathService,
TestFrameworkProductPathService,
diff --git a/src/client/common/types.ts b/src/client/common/types.ts
index 05a8a985a5ff..742948a49652 100644
--- a/src/client/common/types.ts
+++ b/src/client/common/types.ts
@@ -8,7 +8,6 @@ import {
CancellationToken,
ConfigurationChangeEvent,
ConfigurationTarget,
- DiagnosticSeverity,
Disposable,
DocumentSymbolProvider,
Event,
@@ -85,24 +84,14 @@ export enum ProductInstallStatus {
}
export enum ProductType {
- Linter = 'Linter',
TestFramework = 'TestFramework',
- RefactoringLibrary = 'RefactoringLibrary',
DataScience = 'DataScience',
Python = 'Python',
}
export enum Product {
pytest = 1,
- pylint = 3,
- flake8 = 4,
- pycodestyle = 5,
- pylama = 6,
- prospector = 7,
- pydocstyle = 8,
- mypy = 11,
unittest = 12,
- bandit = 17,
tensorboard = 24,
torchProfilerInstallName = 25,
torchProfilerImportName = 26,
@@ -179,7 +168,6 @@ export interface IPythonSettings {
readonly pipenvPath: string;
readonly poetryPath: string;
readonly devOptions: string[];
- readonly linting: ILintingSettings;
readonly testing: ITestingSettings;
readonly autoComplete: IAutoCompleteSettings;
readonly terminal: ITerminalSettings;
@@ -197,67 +185,10 @@ export interface ITensorBoardSettings {
logDirectory: string | undefined;
}
-export interface IPylintCategorySeverity {
- readonly convention: DiagnosticSeverity;
- readonly refactor: DiagnosticSeverity;
- readonly warning: DiagnosticSeverity;
- readonly error: DiagnosticSeverity;
- readonly fatal: DiagnosticSeverity;
-}
-export interface IPycodestyleCategorySeverity {
- readonly W: DiagnosticSeverity;
- readonly E: DiagnosticSeverity;
-}
-
-export interface Flake8CategorySeverity {
- readonly F: DiagnosticSeverity;
- readonly E: DiagnosticSeverity;
- readonly W: DiagnosticSeverity;
-}
-export interface IMypyCategorySeverity {
- readonly error: DiagnosticSeverity;
- readonly note: DiagnosticSeverity;
-}
export interface IInterpreterSettings {
infoVisibility: 'never' | 'onPythonRelated' | 'always';
}
-export interface ILintingSettings {
- readonly enabled: boolean;
- readonly ignorePatterns: string[];
- readonly prospectorEnabled: boolean;
- readonly prospectorArgs: string[];
- readonly pylintEnabled: boolean;
- readonly pylintArgs: string[];
- readonly pycodestyleEnabled: boolean;
- readonly pycodestyleArgs: string[];
- readonly pylamaEnabled: boolean;
- readonly pylamaArgs: string[];
- readonly flake8Enabled: boolean;
- readonly flake8Args: string[];
- readonly pydocstyleEnabled: boolean;
- readonly pydocstyleArgs: string[];
- readonly lintOnSave: boolean;
- readonly maxNumberOfProblems: number;
- readonly pylintCategorySeverity: IPylintCategorySeverity;
- readonly pycodestyleCategorySeverity: IPycodestyleCategorySeverity;
- readonly flake8CategorySeverity: Flake8CategorySeverity;
- readonly mypyCategorySeverity: IMypyCategorySeverity;
- cwd?: string;
- prospectorPath: string;
- pylintPath: string;
- pycodestylePath: string;
- pylamaPath: string;
- flake8Path: string;
- pydocstylePath: string;
- mypyEnabled: boolean;
- mypyArgs: string[];
- mypyPath: string;
- banditEnabled: boolean;
- banditArgs: string[];
- banditPath: string;
-}
-
export interface ITerminalSettings {
readonly executeInFileDir: boolean;
readonly focusAfterLaunch: boolean;
diff --git a/src/client/common/utils/localize.ts b/src/client/common/utils/localize.ts
index bbb55a79ce40..b5d1721d14fa 100644
--- a/src/client/common/utils/localize.ts
+++ b/src/client/common/utils/localize.ts
@@ -506,14 +506,3 @@ export namespace CreateEnv {
export const disableCheckWorkspace = l10n.t('Disable (Workspace)');
}
}
-
-export namespace ToolsExtensions {
- export const flake8PromptMessage = l10n.t(
- 'Use the Flake8 extension to enable easier configuration and new features such as quick fixes.',
- );
- export const pylintPromptMessage = l10n.t(
- 'Use the Pylint extension to enable easier configuration and new features such as quick fixes.',
- );
- export const installPylintExtension = l10n.t('Install Pylint extension');
- export const installFlake8Extension = l10n.t('Install Flake8 extension');
-}
diff --git a/src/client/extensionActivation.ts b/src/client/extensionActivation.ts
index 0d3b04d9bb8c..37ca1ad54afc 100644
--- a/src/client/extensionActivation.ts
+++ b/src/client/extensionActivation.ts
@@ -27,7 +27,6 @@ import { registerTypes as debugConfigurationRegisterTypes } from './debugger/ext
import { IDebugConfigurationService, IDynamicDebugConfigurationService } from './debugger/extension/types';
import { IInterpreterService } from './interpreter/contracts';
import { getLanguageConfiguration } from './language/languageConfiguration';
-import { registerTypes as lintersRegisterTypes } from './linters/serviceRegistry';
import { ReplProvider } from './providers/replProvider';
import { registerTypes as providersRegisterTypes } from './providers/serviceRegistry';
import { TerminalProvider } from './providers/terminalProvider';
@@ -122,7 +121,6 @@ async function activateLegacy(ext: ExtensionState): Promise {
serviceManager.addSingletonInstance(UseProposedApi, enableProposedApi);
// Feature specific registrations.
unitTestsRegisterTypes(serviceManager);
- lintersRegisterTypes(serviceManager);
installerRegisterTypes(serviceManager);
commonRegisterTerminalTypes(serviceManager);
debugConfigurationRegisterTypes(serviceManager);
diff --git a/src/client/linters/bandit.ts b/src/client/linters/bandit.ts
deleted file mode 100644
index bbc8836bfc6b..000000000000
--- a/src/client/linters/bandit.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-'use strict';
-
-import { CancellationToken, TextDocument } from 'vscode';
-import '../common/extensions';
-import { Product } from '../common/types';
-import { IServiceContainer } from '../ioc/types';
-import { BaseLinter } from './baseLinter';
-import { ILintMessage, LintMessageSeverity } from './types';
-
-const severityMapping: Record = {
- LOW: LintMessageSeverity.Information,
- MEDIUM: LintMessageSeverity.Warning,
- HIGH: LintMessageSeverity.Error,
-};
-
-export const BANDIT_REGEX =
- '(?\\d+),(?(col)?(\\d+)?),(?\\w+),(?\\w+\\d+):(?.*)\\r?(\\n|$)';
-
-export class Bandit extends BaseLinter {
- constructor(serviceContainer: IServiceContainer) {
- super(Product.bandit, serviceContainer);
- }
-
- protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise {
- // View all errors in bandit <= 1.5.1 (https://github.com/PyCQA/bandit/issues/371)
- const messages = await this.run([document.uri.fsPath], document, cancellation, BANDIT_REGEX);
-
- messages.forEach((msg) => {
- msg.severity = severityMapping[msg.type];
- });
- return messages;
- }
-}
diff --git a/src/client/linters/baseLinter.ts b/src/client/linters/baseLinter.ts
deleted file mode 100644
index bb24bee1637f..000000000000
--- a/src/client/linters/baseLinter.ts
+++ /dev/null
@@ -1,229 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-'use strict';
-
-import * as path from 'path';
-import * as vscode from 'vscode';
-import { IWorkspaceService } from '../common/application/types';
-import { isTestExecution } from '../common/constants';
-import '../common/extensions';
-import { IPythonToolExecutionService } from '../common/process/types';
-import { splitLines } from '../common/stringUtils';
-import {
- ExecutionInfo,
- Flake8CategorySeverity,
- IConfigurationService,
- IMypyCategorySeverity,
- IPycodestyleCategorySeverity,
- IPylintCategorySeverity,
- IPythonSettings,
- Product,
-} from '../common/types';
-import { IServiceContainer } from '../ioc/types';
-import { traceError, traceLog } from '../logging';
-import { ErrorHandler } from './errorHandlers/errorHandler';
-import { ILinter, ILinterInfo, ILinterManager, ILintMessage, LinterId, LintMessageSeverity } from './types';
-
-const namedRegexp = require('named-js-regexp');
-// Allow negative column numbers (https://github.com/PyCQA/pylint/issues/1822)
-// Allow codes with more than one letter (i.e. ABC123)
-const REGEX = '(?\\d+),(?-?\\d+),(?\\w+),(?\\w+\\d+):(?.*)\\r?(\\n|$)';
-
-interface IRegexGroup {
- line: number;
- column: number;
- code: string;
- message: string;
- type: string;
-}
-
-function matchNamedRegEx(data: string, regex: string): IRegexGroup | undefined {
- const compiledRegexp = namedRegexp(regex, 'g');
- const rawMatch = compiledRegexp.exec(data);
- if (rawMatch !== null) {
- return rawMatch.groups();
- }
-
- return undefined;
-}
-
-export function parseLine(line: string, regex: string, linterID: LinterId, colOffset = 0): ILintMessage | undefined {
- const match = matchNamedRegEx(line, regex)!;
- if (!match) {
- return undefined;
- }
-
- match.line = Number(match.line);
-
- match.column = Number(match.column);
-
- return {
- code: match.code,
- message: match.message,
- column: Number.isNaN(match.column) || match.column <= 0 ? 0 : match.column - colOffset,
- line: match.line,
- type: match.type,
- provider: linterID,
- };
-}
-
-export abstract class BaseLinter implements ILinter {
- protected readonly configService: IConfigurationService;
-
- private errorHandler: ErrorHandler;
-
- private _pythonSettings!: IPythonSettings;
-
- private _info: ILinterInfo;
-
- private workspace: IWorkspaceService;
-
- protected get pythonSettings(): IPythonSettings {
- return this._pythonSettings;
- }
-
- constructor(
- product: Product,
- protected readonly serviceContainer: IServiceContainer,
- protected readonly columnOffset = 0,
- ) {
- this._info = serviceContainer.get(ILinterManager).getLinterInfo(product);
- this.errorHandler = new ErrorHandler(this.info.product, serviceContainer);
- this.configService = serviceContainer.get(IConfigurationService);
- this.workspace = serviceContainer.get(IWorkspaceService);
- }
-
- public get info(): ILinterInfo {
- return this._info;
- }
-
- public async lint(document: vscode.TextDocument, cancellation: vscode.CancellationToken): Promise {
- this._pythonSettings = this.configService.getSettings(document.uri);
- return this.runLinter(document, cancellation);
- }
-
- protected getWorkspaceRootPath(document: vscode.TextDocument): string {
- const workspaceFolder = this.workspace.getWorkspaceFolder(document.uri);
- const workspaceRootPath =
- workspaceFolder && typeof workspaceFolder.uri.fsPath === 'string' ? workspaceFolder.uri.fsPath : undefined;
- return typeof workspaceRootPath === 'string' ? workspaceRootPath : path.dirname(document.uri.fsPath);
- }
-
- protected getWorkingDirectoryPath(document: vscode.TextDocument): string {
- return this._pythonSettings.linting.cwd || this.getWorkspaceRootPath(document);
- }
-
- protected abstract runLinter(
- document: vscode.TextDocument,
- cancellation: vscode.CancellationToken,
- ): Promise;
-
- // eslint-disable-next-line class-methods-use-this
- protected parseMessagesSeverity(
- error: string,
- categorySeverity:
- | Flake8CategorySeverity
- | IMypyCategorySeverity
- | IPycodestyleCategorySeverity
- | IPylintCategorySeverity,
- ): LintMessageSeverity {
- const severity = error as keyof typeof categorySeverity;
-
- if (categorySeverity[severity]) {
- const severityName = categorySeverity[severity];
- switch (severityName) {
- case 'Error':
- return LintMessageSeverity.Error;
- case 'Hint':
- return LintMessageSeverity.Hint;
- case 'Information':
- return LintMessageSeverity.Information;
- case 'Warning':
- return LintMessageSeverity.Warning;
- default: {
- if (LintMessageSeverity[severityName]) {
- return (LintMessageSeverity[severityName] as unknown) as LintMessageSeverity;
- }
- }
- }
- }
- return LintMessageSeverity.Information;
- }
-
- protected async run(
- args: string[],
- document: vscode.TextDocument,
- cancellation: vscode.CancellationToken,
- regEx: string = REGEX,
- ): Promise {
- if (!this.info.isEnabled(document.uri)) {
- return [];
- }
- const executionInfo = this.info.getExecutionInfo(args, document.uri);
- const cwd = this.getWorkingDirectoryPath(document);
- const pythonToolsExecutionService = this.serviceContainer.get(
- IPythonToolExecutionService,
- );
- try {
- const result = await pythonToolsExecutionService.execForLinter(
- executionInfo,
- { cwd, token: cancellation, mergeStdOutErr: false },
- document.uri,
- );
- this.displayLinterResultHeader(result.stdout);
- return await this.parseMessages(result.stdout, document, cancellation, regEx);
- } catch (error) {
- await this.handleError(error as Error, document.uri, executionInfo);
- return [];
- }
- }
-
- protected async parseMessages(
- output: string,
- _document: vscode.TextDocument,
- _token: vscode.CancellationToken,
- regEx: string,
- ): Promise {
- const outputLines = splitLines(output, { removeEmptyEntries: false, trim: false });
- return this.parseLines(outputLines, regEx);
- }
-
- protected async handleError(error: Error, resource: vscode.Uri, execInfo: ExecutionInfo): Promise {
- if (isTestExecution()) {
- this.errorHandler.handleError(error, resource, execInfo).ignoreErrors();
- } else {
- this.errorHandler
- .handleError(error, resource, execInfo)
- .catch((ex) => traceError('Error in errorHandler.handleError', ex))
- .ignoreErrors();
- }
- }
-
- private parseLine(line: string, regEx: string): ILintMessage | undefined {
- return parseLine(line, regEx, this.info.id, this.columnOffset);
- }
-
- private parseLines(outputLines: string[], regEx: string): ILintMessage[] {
- const messages: ILintMessage[] = [];
- for (const line of outputLines) {
- try {
- const msg = this.parseLine(line, regEx);
- if (msg) {
- messages.push(msg);
- if (messages.length >= this.pythonSettings.linting.maxNumberOfProblems) {
- break;
- }
- }
- } catch (ex) {
- traceError(`Linter '${this.info.id}' failed to parse the line '${line}.`, ex);
- }
- }
- return messages;
- }
-
- private displayLinterResultHeader(data: string) {
- traceLog(`${'#'.repeat(10)}Linting Output - ${this.info.id}${'#'.repeat(10)}\n`);
- traceLog(data);
- }
-}
diff --git a/src/client/linters/constants.ts b/src/client/linters/constants.ts
deleted file mode 100644
index 27b7c80db7f4..000000000000
--- a/src/client/linters/constants.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-'use strict';
-
-import { Product } from '../common/types';
-import { LinterId } from './types';
-
-// All supported linters must be in this map.
-export const LINTERID_BY_PRODUCT = new Map([
- [Product.bandit, LinterId.Bandit],
- [Product.flake8, LinterId.Flake8],
- [Product.pylint, LinterId.PyLint],
- [Product.mypy, LinterId.MyPy],
- [Product.pycodestyle, LinterId.PyCodeStyle],
- [Product.prospector, LinterId.Prospector],
- [Product.pydocstyle, LinterId.PyDocStyle],
- [Product.pylama, LinterId.PyLama],
-]);
diff --git a/src/client/linters/errorHandlers/baseErrorHandler.ts b/src/client/linters/errorHandlers/baseErrorHandler.ts
deleted file mode 100644
index 16c5e93ae012..000000000000
--- a/src/client/linters/errorHandlers/baseErrorHandler.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-import { Uri } from 'vscode';
-import { ExecutionInfo, IInstaller, Product } from '../../common/types';
-import { IServiceContainer } from '../../ioc/types';
-import { IErrorHandler } from '../types';
-
-export abstract class BaseErrorHandler implements IErrorHandler {
- protected installer: IInstaller;
-
- private handler?: IErrorHandler;
-
- constructor(protected product: Product, protected serviceContainer: IServiceContainer) {
- this.installer = this.serviceContainer.get(IInstaller);
- }
-
- protected get nextHandler(): IErrorHandler | undefined {
- return this.handler;
- }
-
- public setNextHandler(handler: IErrorHandler): void {
- this.handler = handler;
- }
-
- public abstract handleError(error: Error, resource: Uri, execInfo: ExecutionInfo): Promise;
-}
diff --git a/src/client/linters/errorHandlers/errorHandler.ts b/src/client/linters/errorHandlers/errorHandler.ts
deleted file mode 100644
index af28dd61c3a4..000000000000
--- a/src/client/linters/errorHandlers/errorHandler.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { Uri } from 'vscode';
-import { ExecutionInfo, Product } from '../../common/types';
-import { IServiceContainer } from '../../ioc/types';
-import { IErrorHandler } from '../types';
-import { BaseErrorHandler } from './baseErrorHandler';
-import { StandardErrorHandler } from './standard';
-
-export class ErrorHandler implements IErrorHandler {
- private handler: BaseErrorHandler;
-
- constructor(product: Product, serviceContainer: IServiceContainer) {
- this.handler = new StandardErrorHandler(product, serviceContainer);
- }
-
- public handleError(error: Error, resource: Uri, execInfo: ExecutionInfo): Promise {
- return this.handler.handleError(error, resource, execInfo);
- }
-}
diff --git a/src/client/linters/errorHandlers/standard.ts b/src/client/linters/errorHandlers/standard.ts
deleted file mode 100644
index 6367da7abe4a..000000000000
--- a/src/client/linters/errorHandlers/standard.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import { l10n, Uri } from 'vscode';
-import { IApplicationShell } from '../../common/application/types';
-import { ExecutionInfo, ILogOutputChannel } from '../../common/types';
-import { traceError, traceLog } from '../../logging';
-import { ILinterManager, LinterId } from '../types';
-import { BaseErrorHandler } from './baseErrorHandler';
-
-export class StandardErrorHandler extends BaseErrorHandler {
- public async handleError(error: Error, resource: Uri, execInfo: ExecutionInfo): Promise {
- if (
- typeof error === 'string' &&
- (error as string).includes("OSError: [Errno 2] No such file or directory: '/")
- ) {
- return this.nextHandler ? this.nextHandler.handleError(error, resource, execInfo) : Promise.resolve(false);
- }
-
- const linterManager = this.serviceContainer.get(ILinterManager);
- const info = linterManager.getLinterInfo(execInfo.product!);
-
- traceError(`There was an error in running the linter ${info.id}`, error);
- if (info.id === LinterId.PyLint) {
- traceError('Support for "pylint" is moved to ms-python.pylint extension.');
- traceError(
- 'Please install the extension from: https://marketplace.visualstudio.com/items?itemName=ms-python.pylint',
- );
- } else if (info.id === LinterId.Flake8) {
- traceError('Support for "flake8" is moved to ms-python.flake8 extension.');
- traceError(
- 'Please install the extension from: https://marketplace.visualstudio.com/items?itemName=ms-python.flake8',
- );
- } else if (info.id === LinterId.MyPy) {
- traceError('Support for "mypy" is moved to ms-python.mypy-type-checker extension.');
- traceError(
- 'Please install the extension from: https://marketplace.visualstudio.com/items?itemName=ms-python.mypy-type-checker',
- );
- }
- traceError(`If the error is due to missing ${info.id}, please install ${info.id} using pip manually.`);
- traceError('Learn more here: https://aka.ms/AAlgvkb');
- traceLog(`Linting with ${info.id} failed.`);
- traceLog(error.toString());
-
- this.displayLinterError(info.id).ignoreErrors();
- return true;
- }
-
- private async displayLinterError(linterId: LinterId) {
- const message = l10n.t("There was an error in running the linter '{0}'", linterId);
- const appShell = this.serviceContainer.get(IApplicationShell);
- const outputChannel = this.serviceContainer.get(ILogOutputChannel);
- const action = await appShell.showErrorMessage(message, 'View Errors');
- if (action === 'View Errors') {
- outputChannel.show();
- }
- }
-}
diff --git a/src/client/linters/flake8.ts b/src/client/linters/flake8.ts
deleted file mode 100644
index e79d09158741..000000000000
--- a/src/client/linters/flake8.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { CancellationToken, TextDocument } from 'vscode';
-import '../common/extensions';
-import { Product } from '../common/types';
-import { IServiceContainer } from '../ioc/types';
-import { traceLog } from '../logging';
-import { BaseLinter } from './baseLinter';
-import { isExtensionEnabled } from './prompts/common';
-import { FLAKE8_EXTENSION } from './prompts/flake8Prompt';
-import { IToolsExtensionPrompt } from './prompts/types';
-import { ILintMessage } from './types';
-
-const COLUMN_OFF_SET = 1;
-
-export class Flake8 extends BaseLinter {
- constructor(serviceContainer: IServiceContainer, private readonly prompt: IToolsExtensionPrompt) {
- super(Product.flake8, serviceContainer, COLUMN_OFF_SET);
- }
-
- protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise {
- await this.prompt.showPrompt();
-
- if (isExtensionEnabled(this.serviceContainer, FLAKE8_EXTENSION)) {
- traceLog(
- 'LINTING: Skipping linting from Python extension, since Flake8 extension is installed and enabled.',
- );
- return [];
- }
-
- const messages = await this.run([document.uri.fsPath], document, cancellation);
- messages.forEach((msg) => {
- msg.severity = this.parseMessagesSeverity(msg.type, this.pythonSettings.linting.flake8CategorySeverity);
- // flake8 uses 0th line for some file-wide problems
- // but diagnostics expects positive line numbers.
- if (msg.line === 0) {
- msg.line = 1;
- }
- });
- return messages;
- }
-}
diff --git a/src/client/linters/linterInfo.ts b/src/client/linters/linterInfo.ts
deleted file mode 100644
index 321f23b0f304..000000000000
--- a/src/client/linters/linterInfo.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-import * as path from 'path';
-import { Uri } from 'vscode';
-import { linterScript } from '../common/process/internal/scripts';
-import { ExecutionInfo, IConfigurationService, ILintingSettings, Product } from '../common/types';
-import { ILinterInfo, LinterId } from './types';
-
-export class LinterInfo implements ILinterInfo {
- private _id: LinterId;
-
- private _product: Product;
-
- private _configFileNames: string[];
-
- constructor(
- product: Product,
- id: LinterId,
- protected configService: IConfigurationService,
- configFileNames: string[] = [],
- ) {
- this._product = product;
- this._id = id;
- this._configFileNames = configFileNames;
- }
-
- public get id(): LinterId {
- return this._id;
- }
-
- public get product(): Product {
- return this._product;
- }
-
- public get pathSettingName(): string {
- return `${this.id}Path`;
- }
-
- public get argsSettingName(): string {
- return `${this.id}Args`;
- }
-
- public get enabledSettingName(): string {
- return `${this.id}Enabled`;
- }
-
- public get configFileNames(): string[] {
- return this._configFileNames;
- }
-
- public async enableAsync(enabled: boolean, resource?: Uri): Promise {
- return this.configService.updateSetting(`linting.${this.enabledSettingName}`, enabled, resource);
- }
-
- public isEnabled(resource?: Uri): boolean {
- const settings = this.configService.getSettings(resource);
- const name = this.enabledSettingName as keyof ILintingSettings;
- return settings.linting[name] as boolean;
- }
-
- public pathName(resource?: Uri): string {
- const settings = this.configService.getSettings(resource);
- const name = this.pathSettingName as keyof ILintingSettings;
- return settings.linting[name] as string;
- }
-
- public linterArgs(resource?: Uri): string[] {
- const settings = this.configService.getSettings(resource);
- const name = this.argsSettingName as keyof ILintingSettings;
- const args = settings.linting[name];
- return Array.isArray(args) ? (args as string[]) : [];
- }
-
- public getExecutionInfo(customArgs: string[], resource?: Uri): ExecutionInfo {
- const execPath = this.pathName(resource);
- const args = this.linterArgs(resource).concat(customArgs);
- const script = linterScript();
- if (path.basename(execPath) === execPath) {
- return {
- execPath: undefined,
- args: [script, '-m', this.id, ...args],
- product: this.product,
- moduleName: execPath,
- };
- }
- return {
- execPath,
- moduleName: this.id,
- args: [script, '-p', this.id, execPath, ...args],
- product: this.product,
- };
- }
-}
diff --git a/src/client/linters/linterManager.ts b/src/client/linters/linterManager.ts
deleted file mode 100644
index 72c92aa1c77d..000000000000
--- a/src/client/linters/linterManager.ts
+++ /dev/null
@@ -1,134 +0,0 @@
-/* eslint-disable max-classes-per-file */
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-'use strict';
-
-import { inject, injectable } from 'inversify';
-import { CancellationToken, TextDocument, Uri } from 'vscode';
-import { IConfigurationService, Product } from '../common/types';
-import { IServiceContainer } from '../ioc/types';
-import { traceError } from '../logging';
-import { Bandit } from './bandit';
-import { Flake8 } from './flake8';
-import { LinterInfo } from './linterInfo';
-import { MyPy } from './mypy';
-import { getOrCreateFlake8Prompt } from './prompts/flake8Prompt';
-import { getOrCreatePylintPrompt } from './prompts/pylintPrompt';
-import { Prospector } from './prospector';
-import { Pycodestyle } from './pycodestyle';
-import { PyDocStyle } from './pydocstyle';
-import { PyLama } from './pylama';
-import { Pylint } from './pylint';
-import { ILinter, ILinterInfo, ILinterManager, ILintMessage, LinterId } from './types';
-
-class DisabledLinter implements ILinter {
- constructor(private configService: IConfigurationService) {}
-
- public get info() {
- return new LinterInfo(Product.pylint, LinterId.PyLint, this.configService);
- }
-
- // eslint-disable-next-line class-methods-use-this
- public async lint(_document: TextDocument, _cancellation: CancellationToken): Promise {
- return [];
- }
-}
-
-@injectable()
-export class LinterManager implements ILinterManager {
- protected linters: ILinterInfo[];
-
- constructor(@inject(IConfigurationService) private configService: IConfigurationService) {
- // Note that we use unit tests to ensure all the linters are here.
- this.linters = [
- new LinterInfo(Product.bandit, LinterId.Bandit, this.configService),
- new LinterInfo(Product.flake8, LinterId.Flake8, this.configService),
- new LinterInfo(Product.pylint, LinterId.PyLint, this.configService, ['pylintrc', '.pylintrc']),
- new LinterInfo(Product.mypy, LinterId.MyPy, this.configService),
- new LinterInfo(Product.pycodestyle, LinterId.PyCodeStyle, this.configService),
- new LinterInfo(Product.prospector, LinterId.Prospector, this.configService),
- new LinterInfo(Product.pydocstyle, LinterId.PyDocStyle, this.configService),
- new LinterInfo(Product.pylama, LinterId.PyLama, this.configService),
- ];
- }
-
- public getAllLinterInfos(): ILinterInfo[] {
- return this.linters;
- }
-
- public getLinterInfo(product: Product): ILinterInfo {
- const x = this.linters.findIndex((value, _index, _obj) => value.product === product);
- if (x >= 0) {
- return this.linters[x];
- }
- throw new Error(`Invalid linter '${Product[product]}'`);
- }
-
- public async isLintingEnabled(resource?: Uri): Promise {
- const settings = this.configService.getSettings(resource);
- const activeLintersPresent = await this.getActiveLinters(resource);
- return settings.linting.enabled && activeLintersPresent.length > 0;
- }
-
- public async enableLintingAsync(enable: boolean, resource?: Uri): Promise {
- await this.configService.updateSetting('linting.enabled', enable, resource);
- }
-
- public async getActiveLinters(resource?: Uri): Promise {
- return this.linters.filter((x) => x.isEnabled(resource));
- }
-
- public async setActiveLintersAsync(products: Product[], resource?: Uri): Promise {
- // ensure we only allow valid linters to be set, otherwise leave things alone.
- // filter out any invalid products:
- const validProducts = products.filter((product) => {
- const foundIndex = this.linters.findIndex((validLinter) => validLinter.product === product);
- return foundIndex !== -1;
- });
-
- // if we have valid linter product(s), enable only those
- if (validProducts.length > 0) {
- const active = await this.getActiveLinters(resource);
- for (const x of active) {
- await x.enableAsync(false, resource);
- }
- if (products.length > 0) {
- const toActivate = this.linters.filter((x) => products.findIndex((p) => x.product === p) >= 0);
- for (const x of toActivate) {
- await x.enableAsync(true, resource);
- }
- await this.enableLintingAsync(true, resource);
- }
- }
- }
-
- public async createLinter(product: Product, serviceContainer: IServiceContainer, resource?: Uri): Promise {
- if (!(await this.isLintingEnabled(resource))) {
- return new DisabledLinter(this.configService);
- }
- const error = 'Linter manager: Unknown linter';
- switch (product) {
- case Product.bandit:
- return new Bandit(serviceContainer);
- case Product.flake8:
- return new Flake8(serviceContainer, getOrCreateFlake8Prompt(serviceContainer));
- case Product.pylint:
- return new Pylint(serviceContainer, getOrCreatePylintPrompt(serviceContainer));
- case Product.mypy:
- return new MyPy(serviceContainer);
- case Product.prospector:
- return new Prospector(serviceContainer);
- case Product.pylama:
- return new PyLama(serviceContainer);
- case Product.pydocstyle:
- return new PyDocStyle(serviceContainer);
- case Product.pycodestyle:
- return new Pycodestyle(serviceContainer);
- default:
- traceError(error);
- break;
- }
- throw new Error(error);
- }
-}
diff --git a/src/client/linters/lintingEngine.ts b/src/client/linters/lintingEngine.ts
deleted file mode 100644
index 2a4bf4e10848..000000000000
--- a/src/client/linters/lintingEngine.ts
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-'use strict';
-
-import { inject, injectable } from 'inversify';
-import { Minimatch } from 'minimatch';
-import * as path from 'path';
-import * as vscode from 'vscode';
-import { ICommandManager, IDocumentManager, IWorkspaceService } from '../common/application/types';
-import { Commands } from '../common/constants';
-import { IFileSystem } from '../common/platform/types';
-import { IConfigurationService } from '../common/types';
-import { isNotebookCell, noop } from '../common/utils/misc';
-import { StopWatch } from '../common/utils/stopWatch';
-import { IInterpreterService } from '../interpreter/contracts';
-import { IServiceContainer } from '../ioc/types';
-import { sendTelemetryWhenDone } from '../telemetry';
-import { EventName } from '../telemetry/constants';
-import { LinterTrigger, LintingTelemetry } from '../telemetry/types';
-import { ILinterInfo, ILinterManager, ILintingEngine, ILintMessage, LintMessageSeverity } from './types';
-
-const PYTHON: vscode.DocumentFilter = { language: 'python' };
-
-const lintSeverityToVSSeverity = new Map();
-lintSeverityToVSSeverity.set(LintMessageSeverity.Error, vscode.DiagnosticSeverity.Error);
-lintSeverityToVSSeverity.set(LintMessageSeverity.Hint, vscode.DiagnosticSeverity.Hint);
-lintSeverityToVSSeverity.set(LintMessageSeverity.Information, vscode.DiagnosticSeverity.Information);
-lintSeverityToVSSeverity.set(LintMessageSeverity.Warning, vscode.DiagnosticSeverity.Warning);
-
-@injectable()
-export class LintingEngine implements ILintingEngine {
- private workspace: IWorkspaceService;
-
- private documents: IDocumentManager;
-
- private configurationService: IConfigurationService;
-
- private linterManager: ILinterManager;
-
- private diagnosticCollection: vscode.DiagnosticCollection;
-
- private pendingLintings = new Map();
-
- private fileSystem: IFileSystem;
-
- constructor(@inject(IServiceContainer) private serviceContainer: IServiceContainer) {
- this.documents = serviceContainer.get(IDocumentManager);
- this.workspace = serviceContainer.get(IWorkspaceService);
- this.configurationService = serviceContainer.get(IConfigurationService);
- this.linterManager = serviceContainer.get(ILinterManager);
- this.fileSystem = serviceContainer.get(IFileSystem);
- this.diagnosticCollection = vscode.languages.createDiagnosticCollection('python');
- }
-
- public get diagnostics(): vscode.DiagnosticCollection {
- return this.diagnosticCollection;
- }
-
- public clearDiagnostics(document: vscode.TextDocument): void {
- if (this.diagnosticCollection.has(document.uri)) {
- this.diagnosticCollection.delete(document.uri);
- }
- }
-
- public async lintOpenPythonFiles(trigger: LinterTrigger = 'auto'): Promise {
- this.diagnosticCollection.clear();
- const promises = this.documents.textDocuments.map(async (document) => this.lintDocument(document, trigger));
- await Promise.all(promises);
- return this.diagnosticCollection;
- }
-
- public async lintDocument(document: vscode.TextDocument, trigger: LinterTrigger): Promise {
- if (isNotebookCell(document)) {
- return;
- }
- this.diagnosticCollection.set(document.uri, []);
-
- // Check if we need to lint this document
- if (!(await this.shouldLintDocument(document, trigger))) {
- return;
- }
-
- if (this.pendingLintings.has(document.uri.fsPath)) {
- this.pendingLintings.get(document.uri.fsPath)!.cancel();
- this.pendingLintings.delete(document.uri.fsPath);
- }
-
- const cancelToken = new vscode.CancellationTokenSource();
- cancelToken.token.onCancellationRequested(() => {
- if (this.pendingLintings.has(document.uri.fsPath)) {
- this.pendingLintings.delete(document.uri.fsPath);
- }
- });
-
- this.pendingLintings.set(document.uri.fsPath, cancelToken);
-
- const activeLinters = await this.linterManager.getActiveLinters(document.uri);
- const promises: Promise[] = activeLinters.map(async (info: ILinterInfo) => {
- const stopWatch = new StopWatch();
- const linter = await this.linterManager.createLinter(info.product, this.serviceContainer, document.uri);
- const promise = linter.lint(document, cancelToken.token);
- this.sendLinterRunTelemetry(info, document.uri, promise, stopWatch, trigger);
- return promise;
- });
-
- // linters will resolve asynchronously - keep a track of all
- // diagnostics reported as them come in.
- let diagnostics: vscode.Diagnostic[] = [];
- const settings = this.configurationService.getSettings(document.uri);
-
- for (const p of promises) {
- const msgs = await p;
- if (cancelToken.token.isCancellationRequested) {
- break;
- }
-
- if (this.isDocumentOpen(document.uri)) {
- // Build the message and suffix the message with the name of the linter used.
- for (const m of msgs) {
- diagnostics.push(this.createDiagnostics(m, document));
- }
- // Limit the number of messages to the max value.
- diagnostics = diagnostics.filter((_value, index) => index <= settings.linting.maxNumberOfProblems);
- }
- }
- // Set all diagnostics found in this pass, as this method always clears existing diagnostics.
- this.diagnosticCollection.set(document.uri, diagnostics);
- }
-
- // eslint-disable-next-line class-methods-use-this
- private sendLinterRunTelemetry(
- info: ILinterInfo,
- resource: vscode.Uri,
- promise: Promise,
- stopWatch: StopWatch,
- trigger: LinterTrigger,
- ): void {
- const linterExecutablePathName = info.pathName(resource);
- const properties: LintingTelemetry = {
- tool: info.id,
- hasCustomArgs: info.linterArgs(resource).length > 0,
- trigger,
- executableSpecified: linterExecutablePathName !== info.id,
- };
- sendTelemetryWhenDone(EventName.LINTING, promise, stopWatch, properties);
- }
-
- private isDocumentOpen(uri: vscode.Uri): boolean {
- return this.documents.textDocuments.some((document) => document.uri.fsPath === uri.fsPath);
- }
-
- // eslint-disable-next-line class-methods-use-this
- private createDiagnostics(message: ILintMessage, _document: vscode.TextDocument): vscode.Diagnostic {
- const position = new vscode.Position(message.line - 1, message.column);
- let endPosition: vscode.Position = position;
- if (message.endLine && message.endColumn) {
- endPosition = new vscode.Position(message.endLine - 1, message.endColumn);
- }
- const range = new vscode.Range(position, endPosition);
-
- const severity = lintSeverityToVSSeverity.get(message.severity!)!;
- const diagnostic = new vscode.Diagnostic(range, message.message, severity);
- diagnostic.code = message.code;
- diagnostic.source = message.provider;
- return diagnostic;
- }
-
- private async shouldLintDocument(document: vscode.TextDocument, trigger: LinterTrigger): Promise {
- const interpreterService = this.serviceContainer.get(IInterpreterService);
- const interpreter = await interpreterService.getActiveInterpreter(document.uri);
- if (!interpreter && trigger === 'manual') {
- this.serviceContainer
- .get(ICommandManager)
- .executeCommand(Commands.TriggerEnvironmentSelection, document.uri)
- .then(noop, noop);
- return false;
- }
- if (!(await this.linterManager.isLintingEnabled(document.uri))) {
- this.diagnosticCollection.set(document.uri, []);
- return false;
- }
-
- if (document.languageId !== PYTHON.language) {
- return false;
- }
-
- const workspaceFolder = this.workspace.getWorkspaceFolder(document.uri);
- const workspaceRootPath =
- workspaceFolder && typeof workspaceFolder.uri.fsPath === 'string' ? workspaceFolder.uri.fsPath : undefined;
- const relativeFileName =
- typeof workspaceRootPath === 'string'
- ? path.relative(workspaceRootPath, document.fileName)
- : document.fileName;
-
- const settings = this.configurationService.getSettings(document.uri);
- // { dot: true } is important so dirs like `.venv` will be matched by globs
- const ignoreMinmatches = settings.linting.ignorePatterns.map(
- (pattern) => new Minimatch(pattern, { dot: true }),
- );
- if (ignoreMinmatches.some((matcher) => matcher.match(document.fileName) || matcher.match(relativeFileName))) {
- return false;
- }
- if (document.uri.scheme !== 'file' || !document.uri.fsPath) {
- return false;
- }
- return this.fileSystem.fileExists(document.uri.fsPath);
- }
-}
diff --git a/src/client/linters/mypy.ts b/src/client/linters/mypy.ts
deleted file mode 100644
index f39eef99b422..000000000000
--- a/src/client/linters/mypy.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { CancellationToken, TextDocument } from 'vscode';
-import '../common/extensions';
-import { escapeRegExp } from 'lodash';
-import { Product } from '../common/types';
-import { IServiceContainer } from '../ioc/types';
-import { BaseLinter } from './baseLinter';
-import { ILintMessage } from './types';
-
-export function getRegex(filepath: string): string {
- return `${escapeRegExp(filepath)}:(?\\d+)(:(?\\d+))?: (?\\w+): (?.*)\\r?(\\n|$)`;
-}
-const COLUMN_OFF_SET = 1;
-
-export class MyPy extends BaseLinter {
- constructor(serviceContainer: IServiceContainer) {
- super(Product.mypy, serviceContainer, COLUMN_OFF_SET);
- }
-
- protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise {
- const relativeFilePath = document.uri.fsPath.slice(this.getWorkspaceRootPath(document).length + 1);
- const regex = getRegex(relativeFilePath);
- const messages = await this.run([document.uri.fsPath], document, cancellation, regex);
- messages.forEach((msg) => {
- msg.severity = this.parseMessagesSeverity(msg.type, this.pythonSettings.linting.mypyCategorySeverity);
- msg.code = msg.type;
- });
- return messages;
- }
-}
diff --git a/src/client/linters/prompts/common.ts b/src/client/linters/prompts/common.ts
deleted file mode 100644
index ab88282db607..000000000000
--- a/src/client/linters/prompts/common.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-import * as fs from 'fs-extra';
-import * as path from 'path';
-import { ShowToolsExtensionPrompt } from '../../common/experiments/groups';
-import { IExperimentService, IExtensions, IPersistentState, IPersistentStateFactory } from '../../common/types';
-import { IServiceContainer } from '../../ioc/types';
-import { traceLog } from '../../logging';
-
-export function isExtensionDisabled(serviceContainer: IServiceContainer, extensionId: string): boolean {
- const extensions: IExtensions = serviceContainer.get(IExtensions);
- // When debugging the python extension this `extensionPath` below will point to your repo.
- // If you are debugging this feature then set the `extensionPath` to right location after
- // the next line.
- const pythonExt = extensions.getExtension('ms-python.python');
- if (pythonExt) {
- let found = false;
- traceLog(`Extension search path: ${path.dirname(pythonExt.extensionPath)}`);
- fs.readdirSync(path.dirname(pythonExt.extensionPath), { withFileTypes: false }).forEach((s) => {
- if (s.toString().startsWith(extensionId)) {
- found = true;
- }
- });
- return found;
- }
- return false;
-}
-
-/**
- * Detects if extension is installed and enabled.
- */
-export function isExtensionEnabled(serviceContainer: IServiceContainer, extensionId: string): boolean {
- const extensions: IExtensions = serviceContainer.get(IExtensions);
- const extension = extensions.getExtension(extensionId);
- return extension !== undefined;
-}
-
-export function doNotShowPromptState(
- serviceContainer: IServiceContainer,
- promptKey: string,
-): IPersistentState {
- const persistFactory: IPersistentStateFactory = serviceContainer.get(
- IPersistentStateFactory,
- );
- return persistFactory.createWorkspacePersistentState(promptKey, false);
-}
-
-export function inToolsExtensionsExperiment(serviceContainer: IServiceContainer): Promise {
- const experiments: IExperimentService = serviceContainer.get(IExperimentService);
- return experiments.inExperiment(ShowToolsExtensionPrompt.experiment);
-}
diff --git a/src/client/linters/prompts/flake8Prompt.ts b/src/client/linters/prompts/flake8Prompt.ts
deleted file mode 100644
index fa1969df682a..000000000000
--- a/src/client/linters/prompts/flake8Prompt.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-import { IApplicationEnvironment } from '../../common/application/types';
-import { Common, ToolsExtensions } from '../../common/utils/localize';
-import { executeCommand } from '../../common/vscodeApis/commandApis';
-import { showInformationMessage } from '../../common/vscodeApis/windowApis';
-import { IServiceContainer } from '../../ioc/types';
-import { sendTelemetryEvent } from '../../telemetry';
-import { EventName } from '../../telemetry/constants';
-import { doNotShowPromptState, inToolsExtensionsExperiment, isExtensionDisabled, isExtensionEnabled } from './common';
-import { IToolsExtensionPrompt } from './types';
-
-export const FLAKE8_EXTENSION = 'ms-python.flake8';
-const FLAKE8_PROMPT_DONOTSHOW_KEY = 'showFlake8ExtensionPrompt';
-
-export class Flake8ExtensionPrompt implements IToolsExtensionPrompt {
- private shownThisSession = false;
-
- public constructor(private readonly serviceContainer: IServiceContainer) {}
-
- public async showPrompt(): Promise {
- const isEnabled = isExtensionEnabled(this.serviceContainer, FLAKE8_EXTENSION);
- if (isEnabled || isExtensionDisabled(this.serviceContainer, FLAKE8_EXTENSION)) {
- sendTelemetryEvent(EventName.TOOLS_EXTENSIONS_ALREADY_INSTALLED, undefined, {
- extensionId: FLAKE8_EXTENSION,
- isEnabled,
- });
- return true;
- }
-
- const doNotShow = doNotShowPromptState(this.serviceContainer, FLAKE8_PROMPT_DONOTSHOW_KEY);
- if (this.shownThisSession || doNotShow.value) {
- return false;
- }
-
- if (!(await inToolsExtensionsExperiment(this.serviceContainer))) {
- return false;
- }
-
- this.shownThisSession = true;
- const response = await showInformationMessage(
- ToolsExtensions.flake8PromptMessage,
- ToolsExtensions.installFlake8Extension,
- Common.doNotShowAgain,
- );
-
- if (response === Common.doNotShowAgain) {
- doNotShow.updateValue(true);
- return false;
- }
-
- if (response === ToolsExtensions.installFlake8Extension) {
- const appEnv: IApplicationEnvironment = this.serviceContainer.get(
- IApplicationEnvironment,
- );
- await executeCommand('workbench.extensions.installExtension', FLAKE8_EXTENSION, {
- installPreReleaseVersion: appEnv.extensionChannel === 'insiders',
- });
- return true;
- }
-
- return false;
- }
-}
-
-let _prompt: IToolsExtensionPrompt | undefined;
-export function getOrCreateFlake8Prompt(serviceContainer: IServiceContainer): IToolsExtensionPrompt {
- if (!_prompt) {
- _prompt = new Flake8ExtensionPrompt(serviceContainer);
- }
- return _prompt;
-}
diff --git a/src/client/linters/prompts/pylintPrompt.ts b/src/client/linters/prompts/pylintPrompt.ts
deleted file mode 100644
index 37e583243078..000000000000
--- a/src/client/linters/prompts/pylintPrompt.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-import { IApplicationEnvironment } from '../../common/application/types';
-import { Common, ToolsExtensions } from '../../common/utils/localize';
-import { executeCommand } from '../../common/vscodeApis/commandApis';
-import { showInformationMessage } from '../../common/vscodeApis/windowApis';
-import { IServiceContainer } from '../../ioc/types';
-import { sendTelemetryEvent } from '../../telemetry';
-import { EventName } from '../../telemetry/constants';
-import { doNotShowPromptState, inToolsExtensionsExperiment, isExtensionDisabled, isExtensionEnabled } from './common';
-import { IToolsExtensionPrompt } from './types';
-
-export const PYLINT_EXTENSION = 'ms-python.pylint';
-const PYLINT_PROMPT_DONOTSHOW_KEY = 'showPylintExtensionPrompt';
-
-export class PylintExtensionPrompt implements IToolsExtensionPrompt {
- private shownThisSession = false;
-
- public constructor(private readonly serviceContainer: IServiceContainer) {}
-
- public async showPrompt(): Promise {
- const isEnabled = isExtensionEnabled(this.serviceContainer, PYLINT_EXTENSION);
- if (isEnabled || isExtensionDisabled(this.serviceContainer, PYLINT_EXTENSION)) {
- sendTelemetryEvent(EventName.TOOLS_EXTENSIONS_ALREADY_INSTALLED, undefined, {
- extensionId: PYLINT_EXTENSION,
- isEnabled,
- });
- return true;
- }
-
- const doNotShow = doNotShowPromptState(this.serviceContainer, PYLINT_PROMPT_DONOTSHOW_KEY);
- if (this.shownThisSession || doNotShow.value) {
- return false;
- }
-
- if (!(await inToolsExtensionsExperiment(this.serviceContainer))) {
- return false;
- }
-
- sendTelemetryEvent(EventName.TOOLS_EXTENSIONS_PROMPT_SHOWN, undefined, { extensionId: PYLINT_EXTENSION });
- this.shownThisSession = true;
- const response = await showInformationMessage(
- ToolsExtensions.pylintPromptMessage,
- ToolsExtensions.installPylintExtension,
- Common.doNotShowAgain,
- );
-
- if (response === Common.doNotShowAgain) {
- await doNotShow.updateValue(true);
- sendTelemetryEvent(EventName.TOOLS_EXTENSIONS_PROMPT_DISMISSED, undefined, {
- extensionId: PYLINT_EXTENSION,
- dismissType: 'doNotShow',
- });
- return false;
- }
-
- if (response === ToolsExtensions.installPylintExtension) {
- sendTelemetryEvent(EventName.TOOLS_EXTENSIONS_INSTALL_SELECTED, undefined, {
- extensionId: PYLINT_EXTENSION,
- });
- const appEnv: IApplicationEnvironment = this.serviceContainer.get(
- IApplicationEnvironment,
- );
- await executeCommand('workbench.extensions.installExtension', PYLINT_EXTENSION, {
- installPreReleaseVersion: appEnv.extensionChannel === 'insiders',
- });
- return true;
- }
-
- sendTelemetryEvent(EventName.TOOLS_EXTENSIONS_PROMPT_DISMISSED, undefined, {
- extensionId: PYLINT_EXTENSION,
- dismissType: 'close',
- });
-
- return false;
- }
-}
-
-let _prompt: IToolsExtensionPrompt | undefined;
-export function getOrCreatePylintPrompt(serviceContainer: IServiceContainer): IToolsExtensionPrompt {
- if (!_prompt) {
- _prompt = new PylintExtensionPrompt(serviceContainer);
- }
- return _prompt;
-}
diff --git a/src/client/linters/prompts/types.ts b/src/client/linters/prompts/types.ts
deleted file mode 100644
index d7c884b3a00d..000000000000
--- a/src/client/linters/prompts/types.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-export interface IToolsExtensionPrompt {
- showPrompt(): Promise;
-}
diff --git a/src/client/linters/prospector.ts b/src/client/linters/prospector.ts
deleted file mode 100644
index fa4b3907255b..000000000000
--- a/src/client/linters/prospector.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-import * as path from 'path';
-import { CancellationToken, TextDocument } from 'vscode';
-import '../common/extensions';
-import { Product } from '../common/types';
-import { IServiceContainer } from '../ioc/types';
-import { traceError, traceLog } from '../logging';
-import { BaseLinter } from './baseLinter';
-import { ILintMessage } from './types';
-
-interface IProspectorResponse {
- messages: IProspectorMessage[];
-}
-interface IProspectorMessage {
- source: string;
- message: string;
- code: string;
- location: IProspectorLocation;
-}
-interface IProspectorLocation {
- function: string;
- path: string;
- line: number;
- character: number;
- module: 'beforeFormat';
-}
-
-export class Prospector extends BaseLinter {
- constructor(serviceContainer: IServiceContainer) {
- super(Product.prospector, serviceContainer);
- }
-
- protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise {
- const cwd = this.getWorkingDirectoryPath(document);
- const relativePath = path.relative(cwd, document.uri.fsPath);
- return this.run([relativePath], document, cancellation);
- }
-
- protected async parseMessages(
- output: string,
- _document: TextDocument,
- _token: CancellationToken,
- _regEx: string,
- ): Promise {
- let parsedData: IProspectorResponse;
- try {
- parsedData = JSON.parse(output);
- } catch (ex) {
- traceLog(`${'#'.repeat(10)}Linting Output - ${this.info.id}${'#'.repeat(10)}`);
- traceLog(output);
- traceError('Failed to parse Prospector output', ex);
- return [];
- }
- return parsedData.messages
- .filter((_value, index) => index <= this.pythonSettings.linting.maxNumberOfProblems)
- .map((msg) => {
- const lineNumber =
- msg.location.line === null || Number.isNaN(msg.location.line) ? 1 : msg.location.line;
-
- return {
- code: msg.code,
- message: msg.message,
- column: msg.location.character,
- line: lineNumber,
- type: msg.code,
- provider: `${this.info.id} - ${msg.source}`,
- };
- });
- }
-}
diff --git a/src/client/linters/pycodestyle.ts b/src/client/linters/pycodestyle.ts
deleted file mode 100644
index 30517980e83c..000000000000
--- a/src/client/linters/pycodestyle.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { CancellationToken, TextDocument } from 'vscode';
-import '../common/extensions';
-import { Product } from '../common/types';
-import { IServiceContainer } from '../ioc/types';
-import { BaseLinter } from './baseLinter';
-import { ILintMessage } from './types';
-
-const COLUMN_OFF_SET = 1;
-
-export class Pycodestyle extends BaseLinter {
- constructor(serviceContainer: IServiceContainer) {
- super(Product.pycodestyle, serviceContainer, COLUMN_OFF_SET);
- }
-
- protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise {
- const messages = await this.run([document.uri.fsPath], document, cancellation);
- messages.forEach((msg) => {
- msg.severity = this.parseMessagesSeverity(
- msg.type,
- this.pythonSettings.linting.pycodestyleCategorySeverity,
- );
- });
- return messages;
- }
-}
diff --git a/src/client/linters/pydocstyle.ts b/src/client/linters/pydocstyle.ts
deleted file mode 100644
index 4851190a92ac..000000000000
--- a/src/client/linters/pydocstyle.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-import * as path from 'path';
-import { CancellationToken, TextDocument } from 'vscode';
-import '../common/extensions';
-import { Product } from '../common/types';
-import { IServiceContainer } from '../ioc/types';
-import { traceError } from '../logging';
-import { BaseLinter } from './baseLinter';
-import { ILintMessage, LintMessageSeverity } from './types';
-import { isWindows } from '../common/platform/platformService';
-
-export class PyDocStyle extends BaseLinter {
- constructor(serviceContainer: IServiceContainer) {
- super(Product.pydocstyle, serviceContainer);
- }
-
- protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise {
- const messages = await this.run([document.uri.fsPath], document, cancellation);
- // All messages in pep8 are treated as warnings for now.
- messages.forEach((msg) => {
- msg.severity = LintMessageSeverity.Warning;
- });
-
- return messages;
- }
-
- protected async parseMessages(
- output: string,
- document: TextDocument,
- _token: CancellationToken,
- _regEx: string,
- ): Promise {
- let outputLines = output.split(/\r?\n/g);
- const baseFileName = path.basename(document.uri.fsPath);
-
- // Remember, the first line of the response contains the file name and line number, the next line contains the error message.
- // So we have two lines per message, hence we need to take lines in pairs.
- const maxLines = this.pythonSettings.linting.maxNumberOfProblems * 2;
- // First line is almost always empty.
- const oldOutputLines = outputLines.filter((line) => line.length > 0);
- outputLines = [];
- for (let counter = 0; counter < oldOutputLines.length / 2; counter += 1) {
- outputLines.push(oldOutputLines[2 * counter] + oldOutputLines[2 * counter + 1]);
- }
-
- return (
- outputLines
- .filter((value, index) => index < maxLines && value.indexOf(':') >= 0)
- .map((line) => {
- // Windows will have a : after the drive letter (e.g. c:\).
- if (isWindows()) {
- return line.substring(line.indexOf(`${baseFileName}:`) + baseFileName.length + 1).trim();
- }
- return line.substring(line.indexOf(':') + 1).trim();
- })
- // Iterate through the lines (skipping the messages).
- // So, just iterate the response in pairs.
- .map((line) => {
- try {
- if (line.trim().length === 0) {
- return undefined;
- }
- const lineNumber = parseInt(line.substring(0, line.indexOf(' ')), 10);
- const part = line.substring(line.indexOf(':') + 1).trim();
- const code = part.substring(0, part.indexOf(':')).trim();
- const message = part.substring(part.indexOf(':') + 1).trim();
-
- const sourceLine = document.lineAt(lineNumber - 1).text;
- const trimmedSourceLine = sourceLine.trim();
- const sourceStart = sourceLine.indexOf(trimmedSourceLine);
-
- return {
- code,
- message,
- column: sourceStart,
- line: lineNumber,
- type: '',
- provider: this.info.id,
- } as ILintMessage;
- } catch (ex) {
- traceError(`Failed to parse pydocstyle line '${line}'`, ex);
- }
-
- return undefined;
- })
- .filter((item) => item !== undefined)
- .map((item) => item!)
- );
- }
-}
diff --git a/src/client/linters/pylama.ts b/src/client/linters/pylama.ts
deleted file mode 100644
index d5930c839445..000000000000
--- a/src/client/linters/pylama.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { CancellationToken, TextDocument } from 'vscode';
-import '../common/extensions';
-import { Product } from '../common/types';
-import { IServiceContainer } from '../ioc/types';
-import { BaseLinter } from './baseLinter';
-import { ILintMessage, LintMessageSeverity } from './types';
-
-/**
- * Example messages to parse from PyLama
- * 1. Linter: pycodestyle - recent version removed an extra colon (:) after line:col, hence made it optional in the regex (to be backward compatibile)
- * `src/test_py.py:23:60 [E] E226 missing whitespace around arithmetic operator [pycodestyle]`
- * 2. Linter: mypy - output is missing the error code, something like `E226` - hence made it optional in the regex
- * `src/test_py.py:7:4 [E] Argument 1 to "fn" has incompatible type "str"; expected "int" [mypy]`
- */
-
-const REGEX =
- '(?.py):(?\\d+):(?\\d+):? \\[(?\\w+)\\]( (?\\w\\d+)?:?)? (?.*)\\r?(\\n|$)';
-const COLUMN_OFF_SET = 1;
-
-export class PyLama extends BaseLinter {
- constructor(serviceContainer: IServiceContainer) {
- super(Product.pylama, serviceContainer, COLUMN_OFF_SET);
- }
-
- protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise {
- const messages = await this.run([document.uri.fsPath], document, cancellation, REGEX);
- // All messages in pylama are treated as warnings for now.
- messages.forEach((msg) => {
- msg.severity = LintMessageSeverity.Warning;
- });
-
- return messages;
- }
-}
diff --git a/src/client/linters/pylint.ts b/src/client/linters/pylint.ts
deleted file mode 100644
index 0b635417f906..000000000000
--- a/src/client/linters/pylint.ts
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-import { CancellationToken, TextDocument } from 'vscode';
-import '../common/extensions';
-import { Product } from '../common/types';
-import { IServiceContainer } from '../ioc/types';
-import { traceError, traceLog } from '../logging';
-import { BaseLinter } from './baseLinter';
-import { isExtensionEnabled } from './prompts/common';
-import { PYLINT_EXTENSION } from './prompts/pylintPrompt';
-import { IToolsExtensionPrompt } from './prompts/types';
-import { ILintMessage } from './types';
-
-interface IJsonMessage {
- column: number | null;
- line: number;
- message: string;
- symbol: string;
- type: string;
- endLine?: number | null;
- endColumn?: number | null;
-}
-
-export class Pylint extends BaseLinter {
- constructor(serviceContainer: IServiceContainer, private readonly prompt: IToolsExtensionPrompt) {
- super(Product.pylint, serviceContainer);
- }
-
- protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise {
- await this.prompt.showPrompt();
-
- if (isExtensionEnabled(this.serviceContainer, PYLINT_EXTENSION)) {
- traceLog(
- 'LINTING: Skipping linting from Python extension, since Pylint extension is installed and enabled.',
- );
- return [];
- }
-
- const { uri } = document;
- const settings = this.configService.getSettings(uri);
- const args = [uri.fsPath];
- const messages = await this.run(args, document, cancellation);
- messages.forEach((msg) => {
- msg.severity = this.parseMessagesSeverity(msg.type, settings.linting.pylintCategorySeverity);
- });
- return messages;
- }
-
- private parseOutputMessage(outputMsg: IJsonMessage, colOffset = 0): ILintMessage | undefined {
- // Both 'endLine' and 'endColumn' are only present on pylint 2.12.2+
- // If present, both can still be 'null' if AST node didn't have endLine and / or endColumn information.
- // If 'endColumn' is 'null' or not preset, set it to 'undefined' to
- // prevent the lintingEngine from inferring an error range.
- if (outputMsg.endColumn) {
- outputMsg.endColumn = outputMsg.endColumn <= 0 ? 0 : outputMsg.endColumn - colOffset;
- } else {
- outputMsg.endColumn = undefined;
- }
-
- return {
- code: outputMsg.symbol,
- message: outputMsg.message,
- column: outputMsg.column === null || outputMsg.column <= 0 ? 0 : outputMsg.column - colOffset,
- line: outputMsg.line,
- type: outputMsg.type,
- provider: this.info.id,
- endLine: outputMsg.endLine === null ? undefined : outputMsg.endLine,
- endColumn: outputMsg.endColumn,
- };
- }
-
- protected async parseMessages(
- output: string,
- _document: TextDocument,
- _token: CancellationToken,
- _: string,
- ): Promise {
- const messages: ILintMessage[] = [];
- try {
- const parsedOutput: IJsonMessage[] = JSON.parse(output);
- for (const outputMsg of parsedOutput) {
- const msg = this.parseOutputMessage(outputMsg, this.columnOffset);
- if (msg) {
- messages.push(msg);
- if (messages.length >= this.pythonSettings.linting.maxNumberOfProblems) {
- break;
- }
- }
- }
- } catch (ex) {
- traceError(`Linter '${this.info.id}' failed to parse the output '${output}.`, ex);
- }
- return messages;
- }
-}
diff --git a/src/client/linters/serviceRegistry.ts b/src/client/linters/serviceRegistry.ts
deleted file mode 100644
index 26ada4d0cc8f..000000000000
--- a/src/client/linters/serviceRegistry.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-'use strict';
-
-import { IExtensionActivationService } from '../activation/types';
-import { IServiceManager } from '../ioc/types';
-import { LinterProvider } from '../providers/linterProvider';
-import { LinterManager } from './linterManager';
-import { LintingEngine } from './lintingEngine';
-import { ILinterManager, ILintingEngine } from './types';
-
-export function registerTypes(serviceManager: IServiceManager): void {
- serviceManager.addSingleton(ILintingEngine, LintingEngine);
- serviceManager.addSingleton(ILinterManager, LinterManager);
- serviceManager.addSingleton(IExtensionActivationService, LinterProvider);
-}
diff --git a/src/client/linters/types.ts b/src/client/linters/types.ts
deleted file mode 100644
index b24fe508ea1c..000000000000
--- a/src/client/linters/types.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-'use strict';
-
-import * as vscode from 'vscode';
-import { ExecutionInfo, Product } from '../common/types';
-import { IServiceContainer } from '../ioc/types';
-import { LinterTrigger } from '../telemetry/types';
-
-export interface IErrorHandler {
- handleError(error: Error, resource: vscode.Uri, execInfo: ExecutionInfo): Promise;
-}
-
-export enum LinterId {
- Flake8 = 'flake8',
- MyPy = 'mypy',
- PyCodeStyle = 'pycodestyle',
- Prospector = 'prospector',
- PyDocStyle = 'pydocstyle',
- PyLama = 'pylama',
- PyLint = 'pylint',
- Bandit = 'bandit',
-}
-
-export interface ILinterInfo {
- readonly id: LinterId;
- readonly product: Product;
- readonly pathSettingName: string;
- readonly argsSettingName: string;
- readonly enabledSettingName: string;
- readonly configFileNames: string[];
- enableAsync(enabled: boolean, resource?: vscode.Uri): Promise;
- isEnabled(resource?: vscode.Uri): boolean;
- pathName(resource?: vscode.Uri): string;
- linterArgs(resource?: vscode.Uri): string[];
- getExecutionInfo(customArgs: string[], resource?: vscode.Uri): ExecutionInfo;
-}
-
-export interface ILinter {
- readonly info: ILinterInfo;
- lint(document: vscode.TextDocument, cancellation: vscode.CancellationToken): Promise;
-}
-
-export const ILinterManager = Symbol('ILinterManager');
-export interface ILinterManager {
- getAllLinterInfos(): ILinterInfo[];
- getLinterInfo(product: Product): ILinterInfo;
- getActiveLinters(resource?: vscode.Uri): Promise;
- isLintingEnabled(resource?: vscode.Uri): Promise;
- enableLintingAsync(enable: boolean, resource?: vscode.Uri): Promise;
- setActiveLintersAsync(products: Product[], resource?: vscode.Uri): Promise;
- createLinter(product: Product, serviceContainer: IServiceContainer, resource?: vscode.Uri): Promise;
-}
-
-export interface ILintMessage {
- line: number;
- column: number;
- endLine?: number;
- endColumn?: number;
- code: string | undefined;
- message: string;
- type: string;
- severity?: LintMessageSeverity;
- provider: string;
-}
-export enum LintMessageSeverity {
- Hint,
- Error,
- Warning,
- Information,
-}
-
-export const ILintingEngine = Symbol('ILintingEngine');
-export interface ILintingEngine {
- readonly diagnostics: vscode.DiagnosticCollection;
- lintOpenPythonFiles(trigger?: LinterTrigger): Promise;
- lintDocument(document: vscode.TextDocument, trigger: LinterTrigger): Promise;
- clearDiagnostics(document: vscode.TextDocument): void;
-}
diff --git a/src/client/providers/linterProvider.ts b/src/client/providers/linterProvider.ts
deleted file mode 100644
index 7821eaeccd53..000000000000
--- a/src/client/providers/linterProvider.ts
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-'use strict';
-
-import { inject, injectable } from 'inversify';
-import * as path from 'path';
-import { ConfigurationChangeEvent, Disposable, TextDocument, Uri, workspace } from 'vscode';
-import { IExtensionActivationService } from '../activation/types';
-import { IDocumentManager, IWorkspaceService } from '../common/application/types';
-import { isTestExecution } from '../common/constants';
-import '../common/extensions';
-import { IFileSystem } from '../common/platform/types';
-import { IConfigurationService, IDisposable } from '../common/types';
-import { IInterpreterService } from '../interpreter/contracts';
-import { IServiceContainer } from '../ioc/types';
-import { ILinterManager, ILintingEngine } from '../linters/types';
-
-@injectable()
-export class LinterProvider implements IExtensionActivationService, Disposable {
- public readonly supportedWorkspaceTypes = { untrustedWorkspace: false, virtualWorkspace: false };
-
- private interpreterService: IInterpreterService;
-
- private documents: IDocumentManager;
-
- private configuration: IConfigurationService;
-
- private linterManager: ILinterManager;
-
- private engine: ILintingEngine;
-
- private fs: IFileSystem;
-
- private readonly disposables: IDisposable[] = [];
-
- private workspaceService: IWorkspaceService;
-
- private activatedOnce = false;
-
- constructor(@inject(IServiceContainer) private serviceContainer: IServiceContainer) {
- this.serviceContainer = serviceContainer;
- this.fs = this.serviceContainer.get(IFileSystem);
- this.engine = this.serviceContainer.get(ILintingEngine);
- this.linterManager = this.serviceContainer.get(ILinterManager);
- this.interpreterService = this.serviceContainer.get(IInterpreterService);
- this.documents = this.serviceContainer.get(IDocumentManager);
- this.configuration = this.serviceContainer.get(IConfigurationService);
- this.workspaceService = this.serviceContainer.get(IWorkspaceService);
- }
-
- public async activate(): Promise {
- if (this.activatedOnce) {
- return;
- }
- this.activatedOnce = true;
- this.disposables.push(this.interpreterService.onDidChangeInterpreter(() => this.engine.lintOpenPythonFiles()));
-
- this.documents.onDidOpenTextDocument((e) => this.onDocumentOpened(e), this.disposables);
- this.documents.onDidCloseTextDocument((e) => this.onDocumentClosed(e), this.disposables);
- this.documents.onDidSaveTextDocument((e) => this.onDocumentSaved(e), this.disposables);
-
- const disposable = this.workspaceService.onDidChangeConfiguration(this.lintSettingsChangedHandler.bind(this));
- this.disposables.push(disposable);
-
- // On workspace reopen we don't get `onDocumentOpened` since it is first opened
- // and then the extension is activated. So schedule linting pass now.
- if (!isTestExecution()) {
- const timer = setTimeout(() => this.engine.lintOpenPythonFiles().ignoreErrors(), 1200);
- this.disposables.push({ dispose: () => clearTimeout(timer) });
- }
- }
-
- public dispose(): void {
- this.disposables.forEach((d) => d.dispose());
- }
-
- private isDocumentOpen(uri: Uri): boolean {
- return this.documents.textDocuments.some((document) => this.fs.arePathsSame(document.uri.fsPath, uri.fsPath));
- }
-
- private lintSettingsChangedHandler(e: ConfigurationChangeEvent) {
- // Look for python files that belong to the specified workspace folder.
- workspace.textDocuments.forEach((document) => {
- if (e.affectsConfiguration('python.linting', document.uri)) {
- this.engine.lintDocument(document, 'auto').ignoreErrors();
- }
- });
- }
-
- private onDocumentOpened(document: TextDocument): void {
- this.engine.lintDocument(document, 'auto').ignoreErrors();
- }
-
- private onDocumentSaved(document: TextDocument): void {
- const settings = this.configuration.getSettings(document.uri);
- if (document.languageId === 'python' && settings.linting.enabled && settings.linting.lintOnSave) {
- this.engine.lintDocument(document, 'save').ignoreErrors();
- return;
- }
-
- this.linterManager
- .getActiveLinters(document.uri)
- .then((linters) => {
- const fileName = path.basename(document.uri.fsPath).toLowerCase();
- const watchers = linters.filter((info) => info.configFileNames.indexOf(fileName) >= 0);
- if (watchers.length > 0) {
- setTimeout(() => this.engine.lintOpenPythonFiles(), 1000);
- }
- })
- .ignoreErrors();
- }
-
- private onDocumentClosed(document: TextDocument) {
- if (!document || !document.fileName || !document.uri) {
- return;
- }
- // Check if this document is still open as a duplicate editor.
- if (!this.isDocumentOpen(document.uri)) {
- this.engine.clearDiagnostics(document);
- }
- }
-}
diff --git a/src/client/telemetry/constants.ts b/src/client/telemetry/constants.ts
index 301502a0f6fa..de0980ada257 100644
--- a/src/client/telemetry/constants.ts
+++ b/src/client/telemetry/constants.ts
@@ -6,7 +6,6 @@
export enum EventName {
FORMAT_ON_TYPE = 'FORMAT.FORMAT_ON_TYPE',
EDITOR_LOAD = 'EDITOR.LOAD',
- LINTING = 'LINTING',
REPL = 'REPL',
CREATE_NEW_FILE_COMMAND = 'CREATE_NEW_FILE_COMMAND',
SELECT_INTERPRETER = 'SELECT_INTERPRETER',
@@ -78,10 +77,8 @@ export enum EventName {
DIAGNOSTICS_ACTION = 'DIAGNOSTICS.ACTION',
DIAGNOSTICS_MESSAGE = 'DIAGNOSTICS.MESSAGE',
- SELECT_LINTER = 'LINTING.SELECT',
USE_REPORT_ISSUE_COMMAND = 'USE_REPORT_ISSUE_COMMAND',
- LINTER_NOT_INSTALLED_PROMPT = 'LINTER_NOT_INSTALLED_PROMPT',
HASHED_PACKAGE_NAME = 'HASHED_PACKAGE_NAME',
JEDI_LANGUAGE_SERVER_ENABLED = 'JEDI_LANGUAGE_SERVER.ENABLED',
@@ -115,11 +112,6 @@ export enum EventName {
ENVIRONMENT_CHECK_TRIGGER = 'ENVIRONMENT.CHECK.TRIGGER',
ENVIRONMENT_CHECK_RESULT = 'ENVIRONMENT.CHECK.RESULT',
-
- TOOLS_EXTENSIONS_ALREADY_INSTALLED = 'TOOLS_EXTENSIONS.ALREADY_INSTALLED',
- TOOLS_EXTENSIONS_PROMPT_SHOWN = 'TOOLS_EXTENSIONS.PROMPT_SHOWN',
- TOOLS_EXTENSIONS_INSTALL_SELECTED = 'TOOLS_EXTENSIONS.INSTALL_SELECTED',
- TOOLS_EXTENSIONS_PROMPT_DISMISSED = 'TOOLS_EXTENSIONS.PROMPT_DISMISSED',
}
export enum PlatformErrors {
diff --git a/src/client/telemetry/index.ts b/src/client/telemetry/index.ts
index ba65c4d1913f..cc600d2d59a4 100644
--- a/src/client/telemetry/index.ts
+++ b/src/client/telemetry/index.ts
@@ -13,7 +13,6 @@ import { StopWatch } from '../common/utils/stopWatch';
import { isPromise } from '../common/utils/async';
import { DebugConfigurationType } from '../debugger/extension/types';
import { ConsoleType, TriggerType } from '../debugger/types';
-import { LinterId } from '../linters/types';
import { EnvironmentType, PythonEnvironment } from '../pythonEnvironments/info';
import {
TensorBoardPromptSelection,
@@ -22,7 +21,7 @@ import {
TensorBoardEntrypoint,
} from '../tensorBoard/constants';
import { EventName } from './constants';
-import type { LinterTrigger, TestTool } from './types';
+import type { TestTool } from './types';
/**
* Checks whether telemetry is supported.
@@ -894,33 +893,6 @@ export interface IEventNamePropertyMapping {
hashedName: string;
};
- /**
- * Telemetry event sent with details of selection in prompt
- * `Prompt message` :- 'Linter ${productName} is not installed'
- */
- /* __GDPR__
- "linter_not_installed_prompt" : {
- "tool" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "owner": "karthiknadig" },
- "action": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "owner": "karthiknadig" }
- }
- */
- [EventName.LINTER_NOT_INSTALLED_PROMPT]: {
- /**
- * Name of the linter
- *
- * @type {LinterId}
- */
- tool?: LinterId;
- /**
- * `select` When 'Select linter' option is selected
- * `disablePrompt` When "Don't show again" option is selected
- * `install` When 'Install' option is selected
- *
- * @type {('select' | 'disablePrompt' | 'install')}
- */
- action: 'select' | 'disablePrompt' | 'install';
- };
-
/**
* Telemetry event sent when installing modules
*/
@@ -961,44 +933,6 @@ export interface IEventNamePropertyMapping {
*/
version?: string;
};
- /**
- * Telemetry sent with details immediately after linting a document completes
- */
- /* __GDPR__
- "linting" : {
- "duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "karthiknadig" },
- "tool" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "owner": "karthiknadig" },
- "hascustomargs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "owner": "karthiknadig" },
- "trigger" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "owner": "karthiknadig" },
- "executablespecified" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "owner": "karthiknadig" }
- }
- */
- [EventName.LINTING]: {
- /**
- * Name of the linter being used
- *
- * @type {LinterId}
- */
- tool: LinterId;
- /**
- * If custom arguments for linter is provided in settings.json
- *
- * @type {boolean}
- */
- hasCustomArgs: boolean;
- /**
- * Carries the source which triggered configuration of tests
- *
- * @type {LinterTrigger}
- */
- trigger: LinterTrigger;
- /**
- * Carries `true` if linter executable is specified, `false` otherwise
- *
- * @type {boolean}
- */
- executableSpecified: boolean;
- };
/**
* Telemetry event sent when an environment without contain a python binary is selected.
*/
@@ -1545,25 +1479,6 @@ export interface IEventNamePropertyMapping {
}
*/
[EventName.REPL]: never | undefined;
- /**
- * Telemetry event sent with details of linter selected in quickpick of linter list.
- */
- /* __GDPR__
- "linting.select" : {
- "tool" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "owner": "karthiknadig" },
- "enabled" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "owner": "karthiknadig" }
- }
- */
- [EventName.SELECT_LINTER]: {
- /**
- * The name of the linter
- */
- tool?: LinterId;
- /**
- * Carries `true` if linter is enabled, `false` otherwise
- */
- enabled: boolean;
- };
/**
* Telemetry event sent if and when user configure tests command. This command can be trigerred from multiple places in the extension. (Command palette, prompt etc.)
*/
@@ -2135,53 +2050,6 @@ export interface IEventNamePropertyMapping {
[EventName.ENVIRONMENT_CHECK_RESULT]: {
result: 'criteria-met' | 'criteria-not-met' | 'already-ran' | 'turned-off' | 'no-uri';
};
- /**
- * Telemetry event sent when a linter or formatter extension is already installed.
- */
- /* __GDPR__
- "tools_extensions.already_installed" : {
- "extensionId" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "owner": "karthiknadig" }
- }
- */
- [EventName.TOOLS_EXTENSIONS_ALREADY_INSTALLED]: {
- extensionId: 'ms-python.pylint' | 'ms-python.flake8';
- isEnabled: boolean;
- };
- /**
- * Telemetry event sent when install linter or formatter extension prompt is shown.
- */
- /* __GDPR__
- "tools_extensions.prompt_shown" : {
- "extensionId" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "owner": "karthiknadig" }
- }
- */
- [EventName.TOOLS_EXTENSIONS_PROMPT_SHOWN]: {
- extensionId: 'ms-python.pylint' | 'ms-python.flake8';
- };
- /**
- * Telemetry event sent when clicking to install linter or formatter extension from the suggestion prompt.
- */
- /* __GDPR__
- "tools_extensions.install_selected" : {
- "extensionId" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "owner": "karthiknadig" }
- }
- */
- [EventName.TOOLS_EXTENSIONS_INSTALL_SELECTED]: {
- extensionId: 'ms-python.pylint' | 'ms-python.flake8';
- };
- /**
- * Telemetry event sent when dismissing prompt suggesting to install the linter or formatter extension.
- */
- /* __GDPR__
- "tools_extensions.prompt_dismissed" : {
- "extensionId" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "owner": "karthiknadig" },
- "dismissType" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "owner": "karthiknadig" }
- }
- */
- [EventName.TOOLS_EXTENSIONS_PROMPT_DISMISSED]: {
- extensionId: 'ms-python.pylint' | 'ms-python.flake8';
- dismissType: 'close' | 'doNotShow';
- };
/* __GDPR__
"query-expfeature" : {
"owner": "luabud",
diff --git a/src/client/telemetry/types.ts b/src/client/telemetry/types.ts
index ae98707d94a8..865dca278bf0 100644
--- a/src/client/telemetry/types.ts
+++ b/src/client/telemetry/types.ts
@@ -8,10 +8,6 @@ import { EventName } from './constants';
export type EditorLoadTelemetry = IEventNamePropertyMapping[EventName.EDITOR_LOAD];
-export type LinterTrigger = 'auto' | 'save' | 'manual';
-
-export type LintingTelemetry = IEventNamePropertyMapping[EventName.LINTING];
-
export type PythonInterpreterTelemetry = IEventNamePropertyMapping[EventName.PYTHON_INTERPRETER];
export type DebuggerTelemetry = IEventNamePropertyMapping[EventName.DEBUGGER];
export type TestTool = 'pytest' | 'unittest';
diff --git a/src/test/common.ts b/src/test/common.ts
index 4cc985c795b6..2ef366a3a472 100644
--- a/src/test/common.ts
+++ b/src/test/common.ts
@@ -40,23 +40,12 @@ export enum OSType {
export type PythonSettingKeys =
| 'defaultInterpreterPath'
| 'languageServer'
- | 'linting.lintOnSave'
- | 'linting.enabled'
- | 'linting.pylintEnabled'
- | 'linting.flake8Enabled'
- | 'linting.pycodestyleEnabled'
- | 'linting.pylamaEnabled'
- | 'linting.prospectorEnabled'
- | 'linting.pydocstyleEnabled'
- | 'linting.mypyEnabled'
- | 'linting.banditEnabled'
| 'testing.pytestArgs'
| 'testing.unittestArgs'
| 'formatting.provider'
| 'testing.pytestEnabled'
| 'testing.unittestEnabled'
| 'envFile'
- | 'linting.ignorePatterns'
| 'terminal.activateEnvironment';
async function disposePythonSettings() {
diff --git a/src/test/common/configSettings/configSettings.unit.test.ts b/src/test/common/configSettings/configSettings.unit.test.ts
index e43ac7b7fbd8..83b5b4a3d524 100644
--- a/src/test/common/configSettings/configSettings.unit.test.ts
+++ b/src/test/common/configSettings/configSettings.unit.test.ts
@@ -20,7 +20,6 @@ import {
IAutoCompleteSettings,
IExperiments,
IInterpreterSettings,
- ILintingSettings,
ITerminalSettings,
} from '../../../client/common/types';
import { noop } from '../../../client/common/utils/misc';
@@ -115,7 +114,6 @@ suite('Python Settings', async () => {
// complex settings
config.setup((c) => c.get('interpreter')).returns(() => sourceSettings.interpreter);
- config.setup((c) => c.get('linting')).returns(() => sourceSettings.linting);
config.setup((c) => c.get('autoComplete')).returns(() => sourceSettings.autoComplete);
config.setup((c) => c.get('testing')).returns(() => sourceSettings.testing);
config.setup((c) => c.get('terminal')).returns(() => sourceSettings.terminal);
diff --git a/src/test/common/installer.test.ts b/src/test/common/installer.test.ts
deleted file mode 100644
index 9523572ccfe2..000000000000
--- a/src/test/common/installer.test.ts
+++ /dev/null
@@ -1,331 +0,0 @@
-import * as path from 'path';
-import { instance, mock } from 'ts-mockito';
-import * as TypeMoq from 'typemoq';
-import { ConfigurationTarget, Uri } from 'vscode';
-import { IExtensionSingleActivationService } from '../../client/activation/types';
-import { ActiveResourceService } from '../../client/common/application/activeResource';
-import { ApplicationEnvironment } from '../../client/common/application/applicationEnvironment';
-import { ClipboardService } from '../../client/common/application/clipboard';
-import { ReloadVSCodeCommandHandler } from '../../client/common/application/commands/reloadCommand';
-import { ReportIssueCommandHandler } from '../../client/common/application/commands/reportIssueCommand';
-import { DebugService } from '../../client/common/application/debugService';
-import { DebugSessionTelemetry } from '../../client/common/application/debugSessionTelemetry';
-import { DocumentManager } from '../../client/common/application/documentManager';
-import { Extensions } from '../../client/common/application/extensions';
-import {
- IActiveResourceService,
- IApplicationEnvironment,
- IApplicationShell,
- IClipboard,
- ICommandManager,
- IDebugService,
- IDocumentManager,
- IWorkspaceService,
-} from '../../client/common/application/types';
-import { WorkspaceService } from '../../client/common/application/workspace';
-import { ConfigurationService } from '../../client/common/configuration/service';
-import { ExperimentService } from '../../client/common/experiments/service';
-import { InstallationChannelManager } from '../../client/common/installer/channelManager';
-import { ProductInstaller } from '../../client/common/installer/productInstaller';
-import { LinterProductPathService, TestFrameworkProductPathService } from '../../client/common/installer/productPath';
-import { ProductService } from '../../client/common/installer/productService';
-import {
- IInstallationChannelManager,
- IModuleInstaller,
- IProductPathService,
- IProductService,
-} from '../../client/common/installer/types';
-import { InterpreterPathService } from '../../client/common/interpreterPathService';
-import { BrowserService } from '../../client/common/net/browser';
-import { PersistentStateFactory } from '../../client/common/persistentState';
-import { PathUtils } from '../../client/common/platform/pathUtils';
-import { CurrentProcess } from '../../client/common/process/currentProcess';
-import { ProcessLogger } from '../../client/common/process/logger';
-import { IProcessLogger, IProcessServiceFactory } from '../../client/common/process/types';
-import { TerminalActivator } from '../../client/common/terminal/activator';
-import { PowershellTerminalActivationFailedHandler } from '../../client/common/terminal/activator/powershellFailedHandler';
-import { Bash } from '../../client/common/terminal/environmentActivationProviders/bash';
-import { CommandPromptAndPowerShell } from '../../client/common/terminal/environmentActivationProviders/commandPrompt';
-import { Nushell } from '../../client/common/terminal/environmentActivationProviders/nushell';
-import { CondaActivationCommandProvider } from '../../client/common/terminal/environmentActivationProviders/condaActivationProvider';
-import { PipEnvActivationCommandProvider } from '../../client/common/terminal/environmentActivationProviders/pipEnvActivationProvider';
-import { PyEnvActivationCommandProvider } from '../../client/common/terminal/environmentActivationProviders/pyenvActivationProvider';
-import { TerminalServiceFactory } from '../../client/common/terminal/factory';
-import { TerminalHelper } from '../../client/common/terminal/helper';
-import { SettingsShellDetector } from '../../client/common/terminal/shellDetectors/settingsShellDetector';
-import { TerminalNameShellDetector } from '../../client/common/terminal/shellDetectors/terminalNameShellDetector';
-import { UserEnvironmentShellDetector } from '../../client/common/terminal/shellDetectors/userEnvironmentShellDetector';
-import { VSCEnvironmentShellDetector } from '../../client/common/terminal/shellDetectors/vscEnvironmentShellDetector';
-import {
- IShellDetector,
- ITerminalActivationCommandProvider,
- ITerminalActivationHandler,
- ITerminalActivator,
- ITerminalHelper,
- ITerminalServiceFactory,
- TerminalActivationProviders,
-} from '../../client/common/terminal/types';
-import {
- IBrowserService,
- IConfigurationService,
- ICurrentProcess,
- IExperimentService,
- IExtensions,
- IInstaller,
- IInterpreterPathService,
- IPathUtils,
- IPersistentStateFactory,
- IRandom,
- IsWindows,
- Product,
- ProductType,
-} from '../../client/common/types';
-import { createDeferred } from '../../client/common/utils/async';
-import { IMultiStepInputFactory, MultiStepInputFactory } from '../../client/common/utils/multiStepInput';
-import { Random } from '../../client/common/utils/random';
-import { ImportTracker } from '../../client/telemetry/importTracker';
-import { IImportTracker } from '../../client/telemetry/types';
-import { rootWorkspaceUri, updateSetting } from '../common';
-import { MockModuleInstaller } from '../mocks/moduleInstaller';
-import { MockProcessService } from '../mocks/proc';
-import { UnitTestIocContainer } from '../testing/serviceRegistry';
-import { closeActiveWindows, initializeTest, IS_MULTI_ROOT_TEST, TEST_TIMEOUT } from '../initialize';
-import { IActivatedEnvironmentLaunch } from '../../client/interpreter/contracts';
-import { ActivatedEnvironmentLaunch } from '../../client/interpreter/virtualEnvs/activatedEnvLaunch';
-import {
- IPythonPathUpdaterServiceFactory,
- IPythonPathUpdaterServiceManager,
-} from '../../client/interpreter/configuration/types';
-import { PythonPathUpdaterService } from '../../client/interpreter/configuration/pythonPathUpdaterService';
-import { PythonPathUpdaterServiceFactory } from '../../client/interpreter/configuration/pythonPathUpdaterServiceFactory';
-import { getProductsForInstallerTests } from './productsToTest';
-
-suite('Installer', () => {
- let ioc: UnitTestIocContainer;
- const workspaceUri = Uri.file(path.join(__dirname, '..', '..', '..', 'src', 'test'));
- const resource = IS_MULTI_ROOT_TEST ? workspaceUri : undefined;
- suiteSetup(initializeTest);
- setup(async () => {
- await initializeTest();
- await resetSettings();
- await initializeDI();
- });
- suiteTeardown(async () => {
- await closeActiveWindows();
- await resetSettings();
- });
- teardown(async () => {
- await ioc.dispose();
- await closeActiveWindows();
- });
-
- async function initializeDI() {
- ioc = new UnitTestIocContainer();
- ioc.registerUnitTestTypes();
- ioc.registerFileSystemTypes();
- ioc.registerVariableTypes();
- ioc.registerLinterTypes();
- ioc.registerInterpreterStorageTypes();
-
- ioc.serviceManager.addSingleton(IPersistentStateFactory, PersistentStateFactory);
- ioc.serviceManager.addSingleton(IInstaller, ProductInstaller);
- ioc.serviceManager.addSingleton(IPathUtils, PathUtils);
- ioc.serviceManager.addSingleton(IProcessLogger, ProcessLogger);
- ioc.serviceManager.addSingleton(ICurrentProcess, CurrentProcess);
- ioc.serviceManager.addSingleton(
- IInstallationChannelManager,
- InstallationChannelManager,
- );
- ioc.serviceManager.addSingletonInstance(
- ICommandManager,
- TypeMoq.Mock.ofType().object,
- );
-
- ioc.serviceManager.addSingletonInstance(
- IApplicationShell,
- TypeMoq.Mock.ofType().object,
- );
- ioc.serviceManager.addSingleton(IConfigurationService, ConfigurationService);
- ioc.serviceManager.addSingleton(IWorkspaceService, WorkspaceService);
-
- await ioc.registerMockInterpreterTypes();
- ioc.registerMockProcessTypes();
- ioc.serviceManager.addSingletonInstance(IsWindows, false);
- ioc.serviceManager.addSingletonInstance(IProductService, new ProductService());
- ioc.serviceManager.addSingleton(
- IProductPathService,
- LinterProductPathService,
- ProductType.Linter,
- );
- ioc.serviceManager.addSingleton(
- IProductPathService,
- TestFrameworkProductPathService,
- ProductType.TestFramework,
- );
- ioc.serviceManager.addSingleton(
- IActivatedEnvironmentLaunch,
- ActivatedEnvironmentLaunch,
- );
- ioc.serviceManager.addSingleton(
- IPythonPathUpdaterServiceManager,
- PythonPathUpdaterService,
- );
- ioc.serviceManager.addSingleton(
- IPythonPathUpdaterServiceFactory,
- PythonPathUpdaterServiceFactory,
- );
- ioc.serviceManager.addSingleton(IActiveResourceService, ActiveResourceService);
- ioc.serviceManager.addSingleton(IInterpreterPathService, InterpreterPathService);
- ioc.serviceManager.addSingleton(IExtensions, Extensions);
- ioc.serviceManager.addSingleton(IRandom, Random);
- ioc.serviceManager.addSingleton(ITerminalServiceFactory, TerminalServiceFactory);
- ioc.serviceManager.addSingleton(IClipboard, ClipboardService);
- ioc.serviceManager.addSingleton(IDocumentManager, DocumentManager);
- ioc.serviceManager.addSingleton(IDebugService, DebugService);
- ioc.serviceManager.addSingleton(IApplicationEnvironment, ApplicationEnvironment);
- ioc.serviceManager.addSingleton(IBrowserService, BrowserService);
- ioc.serviceManager.addSingleton(ITerminalActivator, TerminalActivator);
- ioc.serviceManager.addSingleton(
- ITerminalActivationHandler,
- PowershellTerminalActivationFailedHandler,
- );
- ioc.serviceManager.addSingleton(IExperimentService, ExperimentService);
-
- ioc.serviceManager.addSingleton(ITerminalHelper, TerminalHelper);
- ioc.serviceManager.addSingleton(
- ITerminalActivationCommandProvider,
- Bash,
- TerminalActivationProviders.bashCShellFish,
- );
- ioc.serviceManager.addSingleton(
- ITerminalActivationCommandProvider,
- CommandPromptAndPowerShell,
- TerminalActivationProviders.commandPromptAndPowerShell,
- );
- ioc.serviceManager.addSingleton(
- ITerminalActivationCommandProvider,
- Nushell,
- TerminalActivationProviders.nushell,
- );
- ioc.serviceManager.addSingleton(
- ITerminalActivationCommandProvider,
- PyEnvActivationCommandProvider,
- TerminalActivationProviders.pyenv,
- );
- ioc.serviceManager.addSingleton(
- ITerminalActivationCommandProvider,
- CondaActivationCommandProvider,
- TerminalActivationProviders.conda,
- );
- ioc.serviceManager.addSingleton(
- ITerminalActivationCommandProvider,
- PipEnvActivationCommandProvider,
- TerminalActivationProviders.pipenv,
- );
- ioc.serviceManager.addSingleton(IMultiStepInputFactory, MultiStepInputFactory);
- ioc.serviceManager.addSingleton(IImportTracker, ImportTracker);
- ioc.serviceManager.addBinding(IImportTracker, IExtensionSingleActivationService);
- ioc.serviceManager.addSingleton(IShellDetector, TerminalNameShellDetector);
- ioc.serviceManager.addSingleton(IShellDetector, SettingsShellDetector);
- ioc.serviceManager.addSingleton(IShellDetector, UserEnvironmentShellDetector);
- ioc.serviceManager.addSingleton(IShellDetector, VSCEnvironmentShellDetector);
- ioc.serviceManager.addSingleton(
- IExtensionSingleActivationService,
- ReloadVSCodeCommandHandler,
- );
- ioc.serviceManager.addSingleton(
- IExtensionSingleActivationService,
- ReportIssueCommandHandler,
- );
-
- ioc.serviceManager.addSingleton(
- IExtensionSingleActivationService,
- DebugSessionTelemetry,
- );
- }
- async function resetSettings() {
- await updateSetting('linting.pylintEnabled', true, rootWorkspaceUri, ConfigurationTarget.Workspace);
- }
-
- async function testCheckingIfProductIsInstalled(product: Product) {
- const installer = ioc.serviceContainer.get(IInstaller);
- const processService = (await ioc.serviceContainer
- .get(IProcessServiceFactory)
- .create()) as MockProcessService;
- const checkInstalledDef = createDeferred();
- processService.onExec((_file, args, _options, callback) => {
- const moduleName = installer.translateProductToModuleName(product);
- if (args.length > 1 && args[0] === '-c' && args[1] === `import ${moduleName}`) {
- checkInstalledDef.resolve(true);
- }
- callback({ stdout: '' });
- });
- await installer.isInstalled(product, resource);
- await checkInstalledDef.promise;
- }
-
- getProductsForInstallerTests().forEach((prod) => {
- test(`Ensure isInstalled for Product: '${prod.name}' executes the right command`, async function () {
- if (
- new ProductService().getProductType(prod.value) === ProductType.DataScience ||
- new ProductService().getProductType(prod.value) === ProductType.Python
- ) {
- return this.skip();
- }
- ioc.serviceManager.addSingletonInstance(
- IModuleInstaller,
- new MockModuleInstaller('one', false),
- );
- ioc.serviceManager.addSingletonInstance(
- IModuleInstaller,
- new MockModuleInstaller('two', true),
- );
- ioc.serviceManager.addSingletonInstance(ITerminalHelper, instance(mock(TerminalHelper)));
- if (prod.value === Product.unittest) {
- return undefined;
- }
- await testCheckingIfProductIsInstalled(prod.value);
-
- return undefined;
- }).timeout(TEST_TIMEOUT * 3);
- });
-
- async function testInstallingProduct(product: Product) {
- const installer = ioc.serviceContainer.get(IInstaller);
- const checkInstalledDef = createDeferred();
- const moduleInstallers = ioc.serviceContainer.getAll(IModuleInstaller);
- const moduleInstallerOne = moduleInstallers.find((item) => item.displayName === 'two')!;
-
- moduleInstallerOne.on('installModule', (name: Product | string) => {
- if (product === name) {
- checkInstalledDef.resolve();
- }
- });
- await installer.install(product);
- await checkInstalledDef.promise;
- }
-
- getProductsForInstallerTests().forEach((prod) => {
- test(`Ensure install for Product: '${prod.name}' executes the right command in IModuleInstaller`, async function () {
- const productType = new ProductService().getProductType(prod.value);
- if (productType === ProductType.DataScience || productType === ProductType.Python) {
- return this.skip();
- }
- ioc.serviceManager.addSingletonInstance(
- IModuleInstaller,
- new MockModuleInstaller('one', false),
- );
- ioc.serviceManager.addSingletonInstance(
- IModuleInstaller,
- new MockModuleInstaller('two', true),
- );
- ioc.serviceManager.addSingletonInstance(ITerminalHelper, instance(mock(TerminalHelper)));
- if (prod.value === Product.unittest) {
- return undefined;
- }
- await testInstallingProduct(prod.value);
-
- return undefined;
- }).timeout(TEST_TIMEOUT * 3);
- });
-});
diff --git a/src/test/common/installer/installer.invalidPath.unit.test.ts b/src/test/common/installer/installer.invalidPath.unit.test.ts
deleted file mode 100644
index b6738759f0d7..000000000000
--- a/src/test/common/installer/installer.invalidPath.unit.test.ts
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-'use strict';
-
-import { expect, use } from 'chai';
-import * as chaiAsPromised from 'chai-as-promised';
-import * as path from 'path';
-import * as TypeMoq from 'typemoq';
-import { Uri } from 'vscode';
-import { IApplicationShell, IWorkspaceService } from '../../../client/common/application/types';
-import '../../../client/common/extensions';
-import { ProductInstaller } from '../../../client/common/installer/productInstaller';
-import { ProductService } from '../../../client/common/installer/productService';
-import { IProductPathService, IProductService } from '../../../client/common/installer/types';
-import { IPersistentState, IPersistentStateFactory, Product, ProductType } from '../../../client/common/types';
-import { IInterpreterService } from '../../../client/interpreter/contracts';
-import { IServiceContainer } from '../../../client/ioc/types';
-import { PythonEnvironment } from '../../../client/pythonEnvironments/info';
-import { getProductsForInstallerTests } from '../productsToTest';
-
-use(chaiAsPromised);
-
-suite('Module Installer - Invalid Paths', () => {
- [undefined, Uri.file('resource')].forEach((resource) => {
- ['moduleName', path.join('users', 'dev', 'tool', 'executable')].forEach((pathToExecutable) => {
- const isExecutableAModule = path.basename(pathToExecutable) === pathToExecutable;
-
- getProductsForInstallerTests().forEach((product) => {
- let installer: ProductInstaller;
- let serviceContainer: TypeMoq.IMock;
- let app: TypeMoq.IMock;
- let workspaceService: TypeMoq.IMock;
- let productPathService: TypeMoq.IMock;
- let persistentState: TypeMoq.IMock;
-
- setup(function () {
- if (new ProductService().getProductType(product.value) === ProductType.DataScience) {
- return this.skip();
- }
- serviceContainer = TypeMoq.Mock.ofType();
-
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IProductService), TypeMoq.It.isAny()))
- .returns(() => new ProductService());
- app = TypeMoq.Mock.ofType();
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IApplicationShell), TypeMoq.It.isAny()))
- .returns(() => app.object);
- workspaceService = TypeMoq.Mock.ofType();
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IWorkspaceService), TypeMoq.It.isAny()))
- .returns(() => workspaceService.object);
-
- productPathService = TypeMoq.Mock.ofType();
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IProductPathService), TypeMoq.It.isAny()))
- .returns(() => productPathService.object);
-
- const interpreterService = TypeMoq.Mock.ofType();
-
- const pythonInterpreter = TypeMoq.Mock.ofType();
-
- pythonInterpreter.setup((i) => (i as any).then).returns(() => undefined);
- interpreterService
- .setup((i) => i.getActiveInterpreter(TypeMoq.It.isAny()))
- .returns(() => Promise.resolve(pythonInterpreter.object));
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IInterpreterService), TypeMoq.It.isAny()))
- .returns(() => interpreterService.object);
-
- persistentState = TypeMoq.Mock.ofType();
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IPersistentStateFactory), TypeMoq.It.isAny()))
- .returns(() => persistentState.object);
-
- installer = new ProductInstaller(serviceContainer.object);
- });
-
- switch (product.value) {
- case Product.unittest: {
- return;
- }
- default: {
- test(`Ensure invalid path message is ${isExecutableAModule ? 'not displayed' : 'displayed'} ${
- product.name
- } (${resource ? 'With a resource' : 'without a resource'})`, async () => {
- // If the path to executable is a module, then we won't display error message indicating path is invalid.
-
- productPathService
- .setup((p) =>
- p.getExecutableNameFromSettings(TypeMoq.It.isAny(), TypeMoq.It.isValue(resource)),
- )
- .returns(() => pathToExecutable)
- .verifiable(TypeMoq.Times.atLeast(isExecutableAModule ? 0 : 1));
- productPathService
- .setup((p) => p.isExecutableAModule(TypeMoq.It.isAny(), TypeMoq.It.isValue(resource)))
- .returns(() => isExecutableAModule)
- .verifiable(TypeMoq.Times.atLeastOnce());
- const anyParams = [0, 1, 2, 3, 4, 5].map(() => TypeMoq.It.isAny());
- app.setup((a) => a.showErrorMessage(TypeMoq.It.isAny(), ...anyParams))
- .callback((message) => {
- if (!isExecutableAModule) {
- expect(message).contains(pathToExecutable);
- }
- })
- .returns(() => Promise.resolve(undefined))
- .verifiable(TypeMoq.Times.exactly(1));
- const persistValue = TypeMoq.Mock.ofType>();
- persistValue.setup((pv) => pv.value).returns(() => false);
- persistValue.setup((pv) => pv.updateValue(TypeMoq.It.isValue(true)));
- persistentState
- .setup((ps) =>
- ps.createGlobalPersistentState(
- TypeMoq.It.isAnyString(),
- TypeMoq.It.isValue(undefined),
- ),
- )
- .returns(() => persistValue.object);
- await installer.promptToInstall(product.value, resource);
- productPathService.verifyAll();
- });
- }
- }
- });
- });
- });
-});
diff --git a/src/test/common/installer/installer.unit.test.ts b/src/test/common/installer/installer.unit.test.ts
deleted file mode 100644
index 69a5f3678f69..000000000000
--- a/src/test/common/installer/installer.unit.test.ts
+++ /dev/null
@@ -1,621 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-/* eslint-disable max-classes-per-file */
-
-import { assert, expect, use } from 'chai';
-import * as chaiAsPromised from 'chai-as-promised';
-import * as sinon from 'sinon';
-import * as TypeMoq from 'typemoq';
-import { Disposable, Uri, WorkspaceFolder } from 'vscode';
-import { IApplicationShell, IWorkspaceService } from '../../../client/common/application/types';
-import '../../../client/common/extensions';
-import { ProductInstaller } from '../../../client/common/installer/productInstaller';
-import { ProductService } from '../../../client/common/installer/productService';
-import {
- IInstallationChannelManager,
- IModuleInstaller,
- IProductPathService,
- IProductService,
-} from '../../../client/common/installer/types';
-import {
- ExecutionResult,
- IProcessService,
- IProcessServiceFactory,
- IPythonExecutionFactory,
- IPythonExecutionService,
-} from '../../../client/common/process/types';
-import {
- IDisposableRegistry,
- InstallerResponse,
- IPersistentState,
- IPersistentStateFactory,
- Product,
- ProductType,
-} from '../../../client/common/types';
-import { createDeferred, Deferred } from '../../../client/common/utils/async';
-import { IInterpreterService } from '../../../client/interpreter/contracts';
-import { IServiceContainer } from '../../../client/ioc/types';
-import { PythonEnvironment } from '../../../client/pythonEnvironments/info';
-import { sleep } from '../../common';
-import { getProductsForInstallerTests } from '../productsToTest';
-
-use(chaiAsPromised);
-
-suite('Module Installer only', () => {
- [undefined, Uri.file('resource')].forEach((resource) => {
- getProductsForInstallerTests()
- .concat([{ name: 'Unknown product', value: 404 }])
-
- .forEach((product) => {
- let disposables: Disposable[] = [];
- let installer: ProductInstaller;
- let installationChannel: TypeMoq.IMock;
- let moduleInstaller: TypeMoq.IMock;
- let serviceContainer: TypeMoq.IMock;
- let app: TypeMoq.IMock;
- let promptDeferred: Deferred | undefined;
- let workspaceService: TypeMoq.IMock;
- let persistentStore: TypeMoq.IMock;
-
- let productPathService: TypeMoq.IMock;
- let interpreterService: TypeMoq.IMock;
- const productService = new ProductService();
-
- setup(function () {
- if (new ProductService().getProductType(product.value) === ProductType.DataScience) {
- return this.skip();
- }
- promptDeferred = createDeferred();
- serviceContainer = TypeMoq.Mock.ofType();
-
- disposables = [];
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IDisposableRegistry), TypeMoq.It.isAny()))
- .returns(() => disposables);
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IProductService), TypeMoq.It.isAny()))
- .returns(() => productService);
- installationChannel = TypeMoq.Mock.ofType();
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IInstallationChannelManager), TypeMoq.It.isAny()))
- .returns(() => installationChannel.object);
- app = TypeMoq.Mock.ofType();
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IApplicationShell), TypeMoq.It.isAny()))
- .returns(() => app.object);
- workspaceService = TypeMoq.Mock.ofType();
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IWorkspaceService), TypeMoq.It.isAny()))
- .returns(() => workspaceService.object);
- persistentStore = TypeMoq.Mock.ofType();
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IPersistentStateFactory), TypeMoq.It.isAny()))
- .returns(() => persistentStore.object);
-
- moduleInstaller = TypeMoq.Mock.ofType();
-
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- moduleInstaller.setup((x: any) => x.then).returns(() => undefined);
- installationChannel
- .setup((i) => i.getInstallationChannel(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
- .returns(() => Promise.resolve(moduleInstaller.object));
- installationChannel
- .setup((i) => i.getInstallationChannel(TypeMoq.It.isAny()))
- .returns(() => Promise.resolve(moduleInstaller.object));
-
- productPathService = TypeMoq.Mock.ofType();
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IProductPathService), TypeMoq.It.isAny()))
- .returns(() => productPathService.object);
- productPathService
- .setup((p) => p.getExecutableNameFromSettings(TypeMoq.It.isAny(), TypeMoq.It.isValue(resource)))
- .returns(() => 'xyz');
- productPathService
- .setup((p) => p.isExecutableAModule(TypeMoq.It.isAny(), TypeMoq.It.isValue(resource)))
- .returns(() => true);
- interpreterService = TypeMoq.Mock.ofType();
- const pythonInterpreter = TypeMoq.Mock.ofType();
-
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- pythonInterpreter.setup((i) => (i as any).then).returns(() => undefined);
- interpreterService
- .setup((i) => i.getActiveInterpreter(TypeMoq.It.isAny()))
- .returns(() => Promise.resolve(pythonInterpreter.object));
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IInterpreterService), TypeMoq.It.isAny()))
- .returns(() => interpreterService.object);
- installer = new ProductInstaller(serviceContainer.object);
-
- return undefined;
- });
-
- teardown(() => {
- if (new ProductService().getProductType(product.value) === ProductType.DataScience) {
- sinon.restore();
- return;
- }
- // This must be resolved, else all subsequent tests will fail (as this same promise will be used for other tests).
- if (promptDeferred) {
- promptDeferred.resolve();
- }
- disposables.forEach((disposable) => {
- if (disposable) {
- disposable.dispose();
- }
- });
- sinon.restore();
- });
-
- switch (product.value) {
- case 404 as Product: {
- test(`If product type is not recognized, throw error (${
- resource ? 'With a resource' : 'without a resource'
- })`, async () => {
- app.setup((a) =>
- a.showErrorMessage(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()),
- ).verifiable(TypeMoq.Times.never());
- const getProductType = sinon.stub(ProductService.prototype, 'getProductType');
-
- getProductType.returns('random' as ProductType);
- const promise = installer.promptToInstall(product.value, resource);
- await expect(promise).to.eventually.be.rejectedWith(`Unknown product ${product.value}`);
- app.verifyAll();
- assert.ok(getProductType.calledOnce);
- });
- return;
- }
- case Product.unittest: {
- test(`Ensure resource info is passed into the module installer ${product.name} (${
- resource ? 'With a resource' : 'without a resource'
- })`, async () => {
- const response = await installer.install(product.value, resource);
- expect(response).to.be.equal(InstallerResponse.Installed);
- });
- test(`Ensure resource info is passed into the module installer (created using ProductInstaller) ${
- product.name
- } (${resource ? 'With a resource' : 'without a resource'})`, async () => {
- const response = await installer.install(product.value, resource);
- expect(response).to.be.equal(InstallerResponse.Installed);
- });
- break;
- }
-
- default:
- test(`Ensure the prompt is displayed only once, until the prompt is closed, ${product.name} (${
- resource ? 'With a resource' : 'without a resource'
- })`, async () => {
- workspaceService
- .setup((w) => w.getWorkspaceFolder(TypeMoq.It.isValue(resource!)))
- .returns(() => TypeMoq.Mock.ofType().object)
- .verifiable(TypeMoq.Times.exactly(resource ? 5 : 0));
- app.setup((a) =>
- a.showErrorMessage(
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- ),
- )
- .returns(() => promptDeferred!.promise)
- .verifiable(TypeMoq.Times.once());
- const persistVal = TypeMoq.Mock.ofType>();
- persistVal.setup((p) => p.value).returns(() => false);
- persistVal.setup((p) => p.updateValue(TypeMoq.It.isValue(true)));
- persistentStore
- .setup((ps) =>
- ps.createGlobalPersistentState(
- TypeMoq.It.isAnyString(),
- TypeMoq.It.isValue(undefined),
- ),
- )
- .returns(() => persistVal.object);
-
- // Display first prompt.
- installer.promptToInstall(product.value, resource).ignoreErrors();
- await sleep(1);
-
- // Display a few more prompts.
- installer.promptToInstall(product.value, resource).ignoreErrors();
- await sleep(1);
- installer.promptToInstall(product.value, resource).ignoreErrors();
- await sleep(1);
- installer.promptToInstall(product.value, resource).ignoreErrors();
- await sleep(1);
- installer.promptToInstall(product.value, resource).ignoreErrors();
- await sleep(1);
-
- app.verifyAll();
- workspaceService.verifyAll();
- });
- test(`Ensure the prompt is displayed again when previous prompt has been closed, ${
- product.name
- } (${resource ? 'With a resource' : 'without a resource'})`, async () => {
- workspaceService
- .setup((w) => w.getWorkspaceFolder(TypeMoq.It.isValue(resource!)))
- .returns(() => TypeMoq.Mock.ofType().object)
- .verifiable(TypeMoq.Times.exactly(resource ? 3 : 0));
- app.setup((a) =>
- a.showErrorMessage(
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- ),
- )
- .returns(() => Promise.resolve(undefined))
- .verifiable(TypeMoq.Times.exactly(3));
- const persistVal = TypeMoq.Mock.ofType>();
- persistVal.setup((p) => p.value).returns(() => false);
- persistVal.setup((p) => p.updateValue(TypeMoq.It.isValue(true)));
- persistentStore
- .setup((ps) =>
- ps.createGlobalPersistentState(
- TypeMoq.It.isAnyString(),
- TypeMoq.It.isValue(undefined),
- ),
- )
- .returns(() => persistVal.object);
-
- await installer.promptToInstall(product.value, resource);
- await installer.promptToInstall(product.value, resource);
- await installer.promptToInstall(product.value, resource);
-
- app.verifyAll();
- workspaceService.verifyAll();
- });
-
- if (product.value === Product.pylint) {
- test(`Ensure the install prompt is not displayed when the user requests it not be shown again, ${
- product.name
- } (${resource ? 'With a resource' : 'without a resource'})`, async () => {
- workspaceService
- .setup((w) => w.getWorkspaceFolder(TypeMoq.It.isValue(resource!)))
- .returns(() => TypeMoq.Mock.ofType().object)
- .verifiable(TypeMoq.Times.exactly(resource ? 2 : 0));
- app.setup((a) =>
- a.showErrorMessage(
- TypeMoq.It.isAnyString(),
- TypeMoq.It.isValue('Install'),
- TypeMoq.It.isValue('Select Linter'),
- TypeMoq.It.isValue("Don't show again"),
- ),
- )
- .returns(async () => "Don't show again")
- .verifiable(TypeMoq.Times.once());
- const persistVal = TypeMoq.Mock.ofType>();
- let mockPersistVal = false;
- persistVal.setup((p) => p.value).returns(() => mockPersistVal);
- persistVal
- .setup((p) => p.updateValue(TypeMoq.It.isValue(true)))
- .returns(() => {
- mockPersistVal = true;
- return Promise.resolve();
- })
- .verifiable(TypeMoq.Times.once());
- persistentStore
- .setup((ps) =>
- ps.createGlobalPersistentState(
- TypeMoq.It.isAnyString(),
- TypeMoq.It.isValue(undefined),
- ),
- )
- .returns(() => persistVal.object)
- .verifiable(TypeMoq.Times.exactly(3));
-
- // Display first prompt.
- const initialResponse = await installer.promptToInstall(product.value, resource);
-
- // Display a second prompt.
- const secondResponse = await installer.promptToInstall(product.value, resource);
-
- expect(initialResponse).to.be.equal(InstallerResponse.Ignore);
- expect(secondResponse).to.be.equal(InstallerResponse.Ignore);
-
- app.verifyAll();
- workspaceService.verifyAll();
- persistentStore.verifyAll();
- persistVal.verifyAll();
- });
- } else if (productService.getProductType(product.value) === ProductType.Linter) {
- test(`Ensure the 'do not show again' prompt isn't shown for non-pylint linters, ${
- product.name
- } (${resource ? 'With a resource' : 'without a resource'})`, async () => {
- workspaceService
- .setup((w) => w.getWorkspaceFolder(TypeMoq.It.isValue(resource!)))
- .returns(() => TypeMoq.Mock.ofType().object);
- app.setup((a) =>
- a.showErrorMessage(
- TypeMoq.It.isAnyString(),
- TypeMoq.It.isValue('Install'),
- TypeMoq.It.isValue('Select Linter'),
- ),
- )
- .returns(async () => undefined)
- .verifiable(TypeMoq.Times.once());
- app.setup((a) =>
- a.showErrorMessage(
- TypeMoq.It.isAnyString(),
- TypeMoq.It.isValue('Install'),
- TypeMoq.It.isValue('Select Linter'),
- TypeMoq.It.isValue("Don't show again"),
- ),
- )
- .returns(async () => undefined)
- .verifiable(TypeMoq.Times.never());
- const persistVal = TypeMoq.Mock.ofType>();
- let mockPersistVal = false;
- persistVal.setup((p) => p.value).returns(() => mockPersistVal);
- persistVal
- .setup((p) => p.updateValue(TypeMoq.It.isValue(true)))
- .returns(() => {
- mockPersistVal = true;
- return Promise.resolve();
- });
- persistentStore
- .setup((ps) =>
- ps.createGlobalPersistentState(
- TypeMoq.It.isAnyString(),
- TypeMoq.It.isValue(undefined),
- ),
- )
- .returns(() => persistVal.object);
-
- // Display the prompt.
- await installer.promptToInstall(product.value, resource);
-
- // we're just ensuring the 'disable pylint' prompt never appears...
- app.verifyAll();
- });
- }
-
- test(`Ensure resource info is passed into the module installer ${product.name} (${
- resource ? 'With a resource' : 'without a resource'
- })`, async () => {
- moduleInstaller
- .setup((m) =>
- m.installModule(
- TypeMoq.It.isValue(product.value),
- TypeMoq.It.isValue(resource),
- TypeMoq.It.isValue(undefined),
- ),
- )
- .returns(() => Promise.reject(new Error('UnitTesting')));
-
- try {
- await installer.install(product.value, resource);
- } catch (ex) {
- moduleInstaller.verify(
- (m) =>
- m.installModule(
- TypeMoq.It.isValue(product.value),
- TypeMoq.It.isValue(resource),
- TypeMoq.It.isValue(undefined),
- ),
- TypeMoq.Times.once(),
- );
- }
- });
-
- test(`Return InstallerResponse.Ignore for the module installer ${product.name} (${
- resource ? 'With a resource' : 'without a resource'
- }) if installation channel is not defined`, async () => {
- moduleInstaller
- .setup((m) =>
- m.installModule(
- TypeMoq.It.isValue(product.value),
- TypeMoq.It.isValue(resource),
- TypeMoq.It.isValue(undefined),
- ),
- )
- .returns(() => Promise.reject(new Error('UnitTesting')));
- installationChannel.reset();
- installationChannel
- .setup((i) => i.getInstallationChannel(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
- .returns(() => Promise.resolve(undefined));
- try {
- const response = await installer.install(product.value, resource);
- expect(response).to.equal(InstallerResponse.Ignore);
- } catch (ex) {
- assert(false, `Should not throw errors, ${ex}`);
- }
- });
- test(`Ensure resource info is passed into the module installer (created using ProductInstaller) ${
- product.name
- } (${resource ? 'With a resource' : 'without a resource'})`, async () => {
- moduleInstaller
- .setup((m) =>
- m.installModule(
- TypeMoq.It.isValue(product.value),
- TypeMoq.It.isValue(resource),
- TypeMoq.It.isValue(undefined),
- ),
- )
- .returns(() => Promise.reject(new Error('UnitTesting')));
-
- try {
- await installer.install(product.value, resource);
- } catch (ex) {
- moduleInstaller.verify(
- (m) =>
- m.installModule(
- TypeMoq.It.isValue(product.value),
- TypeMoq.It.isValue(resource),
- TypeMoq.It.isValue(undefined),
- ),
- TypeMoq.Times.once(),
- );
- }
- });
- }
- // Test isInstalled()
- if (product.value === Product.unittest) {
- test(`Method isInstalled() returns true for module installer ${product.name} (${
- resource ? 'With a resource' : 'without a resource'
- })`, async () => {
- const result = await installer.isInstalled(product.value, resource);
- expect(result).to.equal(true, 'Should be true');
- });
- } else {
- test(`Method isInstalled() returns true if module is installed for the module installer ${
- product.name
- } (${resource ? 'With a resource' : 'without a resource'})`, async () => {
- const pythonExecutionFactory = TypeMoq.Mock.ofType();
- const pythonExecutionService = TypeMoq.Mock.ofType();
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IPythonExecutionFactory)))
- .returns(() => pythonExecutionFactory.object);
- pythonExecutionFactory
- .setup((p) => p.createActivatedEnvironment(TypeMoq.It.isAny()))
- .returns(() => Promise.resolve(pythonExecutionService.object));
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- pythonExecutionService.setup((p) => (p as any).then).returns(() => undefined);
- pythonExecutionService
- .setup((p) => p.isModuleInstalled(TypeMoq.It.isAny()))
- .returns(() => Promise.resolve(true))
- .verifiable(TypeMoq.Times.once());
-
- const response = await installer.isInstalled(product.value, resource);
- expect(response).to.equal(true, 'Should be true');
- pythonExecutionService.verifyAll();
- });
- test(`Method isInstalled() returns false if module is not installed for the module installer ${
- product.name
- } (${resource ? 'With a resource' : 'without a resource'})`, async () => {
- const pythonExecutionFactory = TypeMoq.Mock.ofType();
- const pythonExecutionService = TypeMoq.Mock.ofType();
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IPythonExecutionFactory)))
- .returns(() => pythonExecutionFactory.object);
- pythonExecutionFactory
- .setup((p) => p.createActivatedEnvironment(TypeMoq.It.isAny()))
- .returns(() => Promise.resolve(pythonExecutionService.object));
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- pythonExecutionService.setup((p) => (p as any).then).returns(() => undefined);
- pythonExecutionService
- .setup((p) => p.isModuleInstalled(TypeMoq.It.isAny()))
- .returns(() => Promise.resolve(false))
- .verifiable(TypeMoq.Times.once());
-
- const response = await installer.isInstalled(product.value, resource);
- expect(response).to.equal(false, 'Should be false');
-
- pythonExecutionService.verifyAll();
- });
- test(`Method isInstalled() returns true if running 'path/to/module_executable --version' succeeds for the module installer ${
- product.name
- } (${resource ? 'With a resource' : 'without a resource'})`, async () => {
- const processServiceFactory = TypeMoq.Mock.ofType();
- const processService = TypeMoq.Mock.ofType();
- serviceContainer
- .setup((c) => c.get(IProcessServiceFactory))
- .returns(() => processServiceFactory.object);
- processServiceFactory
- .setup((p) => p.create(TypeMoq.It.isAny()))
- .returns(() => Promise.resolve(processService.object));
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- processService.setup((p) => (p as any).then).returns(() => undefined);
- const executionResult: ExecutionResult = {
- stdout: 'output',
- };
- processService
- .setup((p) => p.exec(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()))
- .returns(() => Promise.resolve(executionResult))
- .verifiable(TypeMoq.Times.once());
-
- productPathService.reset();
- productPathService
- .setup((p) => p.isExecutableAModule(TypeMoq.It.isAny(), TypeMoq.It.isValue(resource)))
- .returns(() => false);
-
- const response = await installer.isInstalled(product.value, resource);
- expect(response).to.equal(true, 'Should be true');
-
- processService.verifyAll();
- });
- test(`Method isInstalled() returns false if running 'path/to/module_executable --version' fails for the module installer ${
- product.name
- } (${resource ? 'With a resource' : 'without a resource'})`, async () => {
- const processServiceFactory = TypeMoq.Mock.ofType();
- const processService = TypeMoq.Mock.ofType();
- serviceContainer
- .setup((c) => c.get(IProcessServiceFactory))
- .returns(() => processServiceFactory.object);
- processServiceFactory
- .setup((p) => p.create(TypeMoq.It.isAny()))
- .returns(() => Promise.resolve(processService.object));
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- processService.setup((p) => (p as any).then).returns(() => undefined);
- processService
- .setup((p) => p.exec(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()))
- .returns(() => Promise.reject(new Error('Kaboom')))
- .verifiable(TypeMoq.Times.once());
-
- productPathService.reset();
- productPathService
- .setup((p) => p.isExecutableAModule(TypeMoq.It.isAny(), TypeMoq.It.isValue(resource)))
- .returns(() => false);
-
- const response = await installer.isInstalled(product.value, resource);
- expect(response).to.equal(false, 'Should be false');
-
- processService.verifyAll();
- });
- }
-
- // Test promptToInstall() when no interpreter is selected
- test(`If no interpreter is selected, promptToInstall() doesn't prompt for product ${product.name} (${
- resource ? 'With a resource' : 'without a resource'
- })`, async () => {
- workspaceService
- .setup((w) => w.getWorkspaceFolder(TypeMoq.It.isValue(resource!)))
- .returns(() => TypeMoq.Mock.ofType().object)
- .verifiable(TypeMoq.Times.never());
- app.setup((a) =>
- a.showErrorMessage(
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- TypeMoq.It.isAny(),
- ),
- )
- .returns(() => Promise.resolve(undefined))
- .verifiable(TypeMoq.Times.never());
- const persistVal = TypeMoq.Mock.ofType>();
- persistVal.setup((p) => p.value).returns(() => false);
- persistVal.setup((p) => p.updateValue(TypeMoq.It.isValue(true)));
- persistentStore
- .setup((ps) =>
- ps.createGlobalPersistentState(
- TypeMoq.It.isAnyString(),
- TypeMoq.It.isValue(undefined),
- ),
- )
- .returns(() => persistVal.object);
-
- interpreterService.reset();
- interpreterService
- .setup((i) => i.getActiveInterpreter(TypeMoq.It.isAny()))
- .returns(() => Promise.resolve(undefined))
- .verifiable(TypeMoq.Times.once());
- await installer.promptToInstall(product.value, resource);
-
- app.verifyAll();
- interpreterService.verifyAll();
- workspaceService.verifyAll();
- });
- });
- });
-});
diff --git a/src/test/common/installer/moduleInstaller.unit.test.ts b/src/test/common/installer/moduleInstaller.unit.test.ts
index 01ac0e315555..3df64ceb2dec 100644
--- a/src/test/common/installer/moduleInstaller.unit.test.ts
+++ b/src/test/common/installer/moduleInstaller.unit.test.ts
@@ -322,110 +322,6 @@ suite('Module Installer', () => {
terminalService.verifyAll();
}
- if (product.value === Product.pylint) {
- generatePythonInterpreterVersions().forEach((interpreterInfo) => {
- const majorVersion = interpreterInfo.version
- ? interpreterInfo.version.major
- : 0;
- if (majorVersion === 2) {
- const testTitle = `Ensure install arg is \'pylint<2.0.0\' in ${
- interpreterInfo.version ? interpreterInfo.version.raw : ''
- }`;
- if (InstallerClass === PipInstaller) {
- test(testTitle, async () => {
- setActiveInterpreter(interpreterInfo);
- const proxyArgs =
- proxyServer.length === 0 ? [] : ['--proxy', proxyServer];
- const expectedArgs = [
- '-m',
- 'pip',
- ...proxyArgs,
- 'install',
- '-U',
- '"pylint<2.0.0"',
- ];
- await installModuleAndVerifyCommand(pythonPath, expectedArgs);
- });
- }
- if (InstallerClass === PipEnvInstaller) {
- test(testTitle, async () => {
- setActiveInterpreter(interpreterInfo);
- const expectedArgs = ['install', '"pylint<2.0.0"', '--dev'];
- await installModuleAndVerifyCommand(pipenvName, expectedArgs);
- });
- }
- if (InstallerClass === CondaInstaller) {
- test(testTitle, async () => {
- setActiveInterpreter(interpreterInfo);
- const expectedArgs = ['install'];
- if (condaEnvInfo && condaEnvInfo.name) {
- expectedArgs.push('--name');
- expectedArgs.push(
- condaEnvInfo.name.toCommandArgumentForPythonExt(),
- );
- } else if (condaEnvInfo && condaEnvInfo.path) {
- expectedArgs.push('--prefix');
- expectedArgs.push(
- condaEnvInfo.path.fileToCommandArgumentForPythonExt(),
- );
- }
- expectedArgs.push('"pylint<2.0.0"');
- expectedArgs.push('-y');
- await installModuleAndVerifyCommand(condaExecutable, expectedArgs);
- });
- }
- } else {
- const testTitle = `Ensure install arg is \'pylint\' in ${
- interpreterInfo.version ? interpreterInfo.version.raw : ''
- }`;
- if (InstallerClass === PipInstaller) {
- test(testTitle, async () => {
- setActiveInterpreter(interpreterInfo);
- const proxyArgs =
- proxyServer.length === 0 ? [] : ['--proxy', proxyServer];
- const expectedArgs = [
- '-m',
- 'pip',
- ...proxyArgs,
- 'install',
- '-U',
- 'pylint',
- ];
- await installModuleAndVerifyCommand(pythonPath, expectedArgs);
- });
- }
- if (InstallerClass === PipEnvInstaller) {
- test(testTitle, async () => {
- setActiveInterpreter(interpreterInfo);
- const expectedArgs = ['install', 'pylint', '--dev'];
- await installModuleAndVerifyCommand(pipenvName, expectedArgs);
- });
- }
- if (InstallerClass === CondaInstaller) {
- test(testTitle, async () => {
- setActiveInterpreter(interpreterInfo);
- const expectedArgs = ['install'];
- if (condaEnvInfo && condaEnvInfo.name) {
- expectedArgs.push('--name');
- expectedArgs.push(
- condaEnvInfo.name.toCommandArgumentForPythonExt(),
- );
- } else if (condaEnvInfo && condaEnvInfo.path) {
- expectedArgs.push('--prefix');
- expectedArgs.push(
- condaEnvInfo.path.fileToCommandArgumentForPythonExt(),
- );
- }
- expectedArgs.push('pylint');
- expectedArgs.push('-y');
- await installModuleAndVerifyCommand(condaExecutable, expectedArgs);
- });
- }
- }
- });
- return;
- }
-
if (InstallerClass === TestModuleInstaller) {
suite(`If interpreter type is Unknown (${product.name})`, async () => {
test(`If 'python.globalModuleInstallation' is set to true and pythonPath directory is read only, do an elevated install`, async () => {
@@ -692,21 +588,6 @@ suite('Module Installer', () => {
});
});
-function generatePythonInterpreterVersions() {
- const versions: SemVer[] = ['2.7.0-final', '3.4.0-final', '3.5.0-final', '3.6.0-final', '3.7.0-final'].map(
- (ver) => new SemVer(ver),
- );
- return versions.map((version) => {
- const info = TypeMoq.Mock.ofType();
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- info.setup((t: any) => t.then).returns(() => undefined);
- info.setup((t) => t.envType).returns(() => EnvironmentType.VirtualEnv);
- info.setup((t) => t.version).returns(() => version);
- info.setup((t) => t.path).returns(() => pythonPath);
- return info.object;
- });
-}
-
function getModuleNamesForTesting(): { name: string; value: Product; moduleName: string }[] {
return getNamesAndValues(Product)
.map((product) => {
diff --git a/src/test/common/installer/productPath.unit.test.ts b/src/test/common/installer/productPath.unit.test.ts
deleted file mode 100644
index 8e65f3a5caed..000000000000
--- a/src/test/common/installer/productPath.unit.test.ts
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-'use strict';
-
-import { fail } from 'assert';
-import { expect, use } from 'chai';
-import * as chaiAsPromised from 'chai-as-promised';
-import * as TypeMoq from 'typemoq';
-import { Uri } from 'vscode';
-import '../../../client/common/extensions';
-import { ProductInstaller } from '../../../client/common/installer/productInstaller';
-import {
- BaseProductPathsService,
- LinterProductPathService,
- TestFrameworkProductPathService,
-} from '../../../client/common/installer/productPath';
-import { ProductService } from '../../../client/common/installer/productService';
-import { IProductService } from '../../../client/common/installer/types';
-import { IConfigurationService, IInstaller, IPythonSettings, Product, ProductType } from '../../../client/common/types';
-import { IServiceContainer } from '../../../client/ioc/types';
-import { ILinterInfo, ILinterManager } from '../../../client/linters/types';
-import { ITestsHelper } from '../../../client/testing/common/types';
-import { ITestingSettings } from '../../../client/testing/configuration/types';
-import { getProductsForInstallerTests } from '../productsToTest';
-
-use(chaiAsPromised);
-
-suite('Product Path', () => {
- [undefined, Uri.file('resource')].forEach((resource) => {
- getProductsForInstallerTests().forEach((product) => {
- class TestBaseProductPathsService extends BaseProductPathsService {
- public getExecutableNameFromSettings(_: Product, _resource?: Uri): string {
- return '';
- }
- }
- let serviceContainer: TypeMoq.IMock;
- let unitTestSettings: TypeMoq.IMock;
- let configService: TypeMoq.IMock;
- let productInstaller: ProductInstaller;
- setup(function () {
- if (new ProductService().getProductType(product.value) === ProductType.DataScience) {
- return this.skip();
- }
- serviceContainer = TypeMoq.Mock.ofType();
- configService = TypeMoq.Mock.ofType();
- unitTestSettings = TypeMoq.Mock.ofType();
-
- productInstaller = new ProductInstaller(serviceContainer.object);
- const pythonSettings = TypeMoq.Mock.ofType();
- pythonSettings.setup((p) => p.testing).returns(() => unitTestSettings.object);
- configService
- .setup((s) => s.getSettings(TypeMoq.It.isValue(resource)))
- .returns(() => pythonSettings.object);
- serviceContainer
- .setup((s) => s.get(TypeMoq.It.isValue(IConfigurationService), TypeMoq.It.isAny()))
- .returns(() => configService.object);
- serviceContainer
- .setup((s) => s.get(TypeMoq.It.isValue(IInstaller), TypeMoq.It.isAny()))
- .returns(() => productInstaller);
- serviceContainer
- .setup((c) => c.get(TypeMoq.It.isValue(IProductService), TypeMoq.It.isAny()))
- .returns(() => new ProductService());
- });
-
- suite('Method isExecutableAModule()', () => {
- test('Returns true if User has customized the executable name', () => {
- productInstaller.translateProductToModuleName = () => 'moduleName';
- const productPathService = new TestBaseProductPathsService(serviceContainer.object);
- productPathService.getExecutableNameFromSettings = () => 'executableName';
- expect(productPathService.isExecutableAModule(product.value)).to.equal(true, 'Should be true');
- });
- test('Returns false if User has customized the full path to executable', () => {
- productInstaller.translateProductToModuleName = () => 'moduleName';
- const productPathService = new TestBaseProductPathsService(serviceContainer.object);
- productPathService.getExecutableNameFromSettings = () => 'path/to/executable';
- expect(productPathService.isExecutableAModule(product.value)).to.equal(false, 'Should be false');
- });
- test('Returns false if translating product to module name fails with error', () => {
- productInstaller.translateProductToModuleName = () => {
- return new Error('Kaboom') as any;
- };
- const productPathService = new TestBaseProductPathsService(serviceContainer.object);
- productPathService.getExecutableNameFromSettings = () => 'executableName';
- expect(productPathService.isExecutableAModule(product.value)).to.equal(false, 'Should be false');
- });
- });
- const productType = new ProductService().getProductType(product.value);
- switch (productType) {
- case ProductType.Linter: {
- test(`Ensure path is returned for ${product.name} (${
- resource ? 'With a resource' : 'without a resource'
- })`, async () => {
- const productPathService = new LinterProductPathService(serviceContainer.object);
- const linterManager = TypeMoq.Mock.ofType();
- const linterInfo = TypeMoq.Mock.ofType