diff --git a/CHANGELOG.md b/CHANGELOG.md index de2615faa33e..0a91b3dcc53a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,66 @@ # Changelog +## 2020.5.1 (19 May 2020) + +### Fixes + +1. Do not execute shebang as an interpreter until user has clicked on the codelens enclosing the shebang. + ([#11687](https://github.com/Microsoft/vscode-python/issues/11687)) + +### Thanks + +Thanks to the following projects which we fully rely on to provide some of +our features: + +- [debugpy](https://pypi.org/project/debugpy/) +- [isort](https://pypi.org/project/isort/) +- [jedi](https://pypi.org/project/jedi/) + and [parso](https://pypi.org/project/parso/) +- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server) +- [ptvsd](https://pypi.org/project/ptvsd/) +- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed) +- [rope](https://pypi.org/project/rope/) (user-installed) + +Also thanks to the various projects we provide integrations with which help +make this extension useful: + +- Debugging support: + [Django](https://pypi.org/project/Django/), + [Flask](https://pypi.org/project/Flask/), + [gevent](https://pypi.org/project/gevent/), + [Jinja](https://pypi.org/project/Jinja/), + [Pyramid](https://pypi.org/project/pyramid/), + [PySpark](https://pypi.org/project/pyspark/), + [Scrapy](https://pypi.org/project/Scrapy/), + [Watson](https://pypi.org/project/Watson/) +- Formatting: + [autopep8](https://pypi.org/project/autopep8/), + [black](https://pypi.org/project/black/), + [yapf](https://pypi.org/project/yapf/) +- Interpreter support: + [conda](https://conda.io/), + [direnv](https://direnv.net/), + [pipenv](https://pypi.org/project/pipenv/), + [pyenv](https://github.com/pyenv/pyenv), + [venv](https://docs.python.org/3/library/venv.html#module-venv), + [virtualenv](https://pypi.org/project/virtualenv/) +- Linting: + [bandit](https://pypi.org/project/bandit/), + [flake8](https://pypi.org/project/flake8/), + [mypy](https://pypi.org/project/mypy/), + [prospector](https://pypi.org/project/prospector/), + [pylint](https://pypi.org/project/pylint/), + [pydocstyle](https://pypi.org/project/pydocstyle/), + [pylama](https://pypi.org/project/pylama/) +- Testing: + [nose](https://pypi.org/project/nose/), + [pytest](https://pypi.org/project/pytest/), + [unittest](https://docs.python.org/3/library/unittest.html#module-unittest) + +And finally thanks to the [Python](https://www.python.org/) development team and +community for creating a fantastic programming language and community to be a +part of! + ## 2020.5.0 (12 May 2020) ### Enhancements diff --git a/package-lock.json b/package-lock.json index a87bf84d4bf8..aae95237a16e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "python", - "version": "2020.5.0", + "version": "2020.5.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 96950926fd56..4b8dc7e22bb9 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "python", "displayName": "Python", "description": "Linting, Debugging (multi-threaded, remote), Intellisense, Jupyter Notebooks, code formatting, refactoring, unit tests, snippets, and more.", - "version": "2020.5.0", + "version": "2020.5.1", "featureFlags": { "usingNewInterpreterStorage": true }, diff --git a/src/client/interpreter/configuration/interpreterSelector/commands/setShebangInterpreter.ts b/src/client/interpreter/configuration/interpreterSelector/commands/setShebangInterpreter.ts index 82834395f976..e3e63b299f83 100644 --- a/src/client/interpreter/configuration/interpreterSelector/commands/setShebangInterpreter.ts +++ b/src/client/interpreter/configuration/interpreterSelector/commands/setShebangInterpreter.ts @@ -37,7 +37,8 @@ export class SetShebangInterpreterCommand extends BaseInterpreterSelectorCommand protected async setShebangInterpreter(): Promise { const shebang = await this.shebangCodeLensProvider.detectShebang( - this.documentManager.activeTextEditor!.document + this.documentManager.activeTextEditor!.document, + true ); if (!shebang) { return; diff --git a/src/client/interpreter/contracts.ts b/src/client/interpreter/contracts.ts index 6013ff504bd2..55b203667ab7 100644 --- a/src/client/interpreter/contracts.ts +++ b/src/client/interpreter/contracts.ts @@ -114,7 +114,7 @@ export interface IInterpreterDisplay { export const IShebangCodeLensProvider = Symbol('IShebangCodeLensProvider'); export interface IShebangCodeLensProvider extends CodeLensProvider { - detectShebang(document: TextDocument): Promise; + detectShebang(document: TextDocument, resolveShebangAsInterpreter?: boolean): Promise; } export const IInterpreterHelper = Symbol('IInterpreterHelper'); diff --git a/src/client/interpreter/display/shebangCodeLensProvider.ts b/src/client/interpreter/display/shebangCodeLensProvider.ts index f545abe86de9..8737981c8369 100644 --- a/src/client/interpreter/display/shebangCodeLensProvider.ts +++ b/src/client/interpreter/display/shebangCodeLensProvider.ts @@ -19,7 +19,10 @@ export class ShebangCodeLensProvider implements IShebangCodeLensProvider { // tslint:disable-next-line:no-any this.onDidChangeCodeLenses = (workspaceService.onDidChangeConfiguration as any) as Event; } - public async detectShebang(document: TextDocument): Promise { + public async detectShebang( + document: TextDocument, + resolveShebangAsInterpreter: boolean = false + ): Promise { const firstLine = document.lineAt(0); if (firstLine.isEmptyOrWhitespace) { return; @@ -30,8 +33,12 @@ export class ShebangCodeLensProvider implements IShebangCodeLensProvider { } const shebang = firstLine.text.substr(2).trim(); - const pythonPath = await this.getFullyQualifiedPathToInterpreter(shebang, document.uri); - return typeof pythonPath === 'string' && pythonPath.length > 0 ? pythonPath : undefined; + if (resolveShebangAsInterpreter) { + const pythonPath = await this.getFullyQualifiedPathToInterpreter(shebang, document.uri); + return typeof pythonPath === 'string' && pythonPath.length > 0 ? pythonPath : undefined; + } else { + return typeof shebang === 'string' && shebang.length > 0 ? shebang : undefined; + } } public async provideCodeLenses(document: TextDocument, _token?: CancellationToken): Promise { return this.createShebangCodeLens(document); diff --git a/src/test/providers/shebangCodeLenseProvider.unit.test.ts b/src/test/providers/shebangCodeLenseProvider.unit.test.ts index 76edd0facae4..c878cb34a9fa 100644 --- a/src/test/providers/shebangCodeLenseProvider.unit.test.ts +++ b/src/test/providers/shebangCodeLenseProvider.unit.test.ts @@ -63,15 +63,33 @@ suite('Shebang detection', () => { return [doc, line]; } - test('Shebang should be empty when first line is empty', async () => { + test('Shebang should be empty when first line is empty when resolving shebang as interpreter', async () => { const [document, line] = createDocument(''); - const shebang = await provider.detectShebang(document.object); + const shebang = await provider.detectShebang(document.object, true); document.verifyAll(); line.verifyAll(); expect(shebang).to.be.equal(undefined, 'Shebang should be undefined'); }); + test('Shebang should be empty when first line is empty when not resolving shebang as interpreter', async () => { + const [document, line] = createDocument(''); + + const shebang = await provider.detectShebang(document.object, false); + + document.verifyAll(); + line.verifyAll(); + expect(shebang).to.be.equal(undefined, 'Shebang should be undefined'); + }); + test('Shebang should be returned as it is when not resolving shebang as interpreter', async () => { + const [document, line] = createDocument('#!HELLO'); + + const shebang = await provider.detectShebang(document.object, false); + + document.verifyAll(); + line.verifyAll(); + expect(shebang).to.be.equal('HELLO', 'Shebang should be HELLO'); + }); test('Shebang should be empty when python path is invalid in shebang', async () => { const [document, line] = createDocument('#!HELLO'); @@ -80,7 +98,7 @@ suite('Shebang detection', () => { .returns(() => Promise.reject()) .verifiable(typemoq.Times.once()); - const shebang = await provider.detectShebang(document.object); + const shebang = await provider.detectShebang(document.object, true); document.verifyAll(); line.verifyAll(); @@ -95,7 +113,7 @@ suite('Shebang detection', () => { .returns(() => Promise.resolve({ stdout: 'THIS_IS_IT' })) .verifiable(typemoq.Times.once()); - const shebang = await provider.detectShebang(document.object); + const shebang = await provider.detectShebang(document.object, true); document.verifyAll(); line.verifyAll(); @@ -113,7 +131,7 @@ suite('Shebang detection', () => { .returns(() => Promise.resolve({ stdout: 'THIS_IS_IT' })) .verifiable(typemoq.Times.once()); - const shebang = await provider.detectShebang(document.object); + const shebang = await provider.detectShebang(document.object, true); document.verifyAll(); line.verifyAll(); @@ -132,7 +150,7 @@ suite('Shebang detection', () => { .returns(() => Promise.resolve({ stdout: 'THIS_IS_IT' })) .verifiable(typemoq.Times.once()); - const shebang = await provider.detectShebang(document.object); + const shebang = await provider.detectShebang(document.object, true); document.verifyAll(); line.verifyAll();