Skip to content

Commit 8c9d5bd

Browse files
authored
Cherry picks, change log, and version update for point release. (#13666)
* Add install telemetry (#13653) * Add extension install telemetry. * Add tests. * Fix typo * Fix tests. * Update comment to reflect what the installed actually does. * Update change log and version for point release.
1 parent 687e141 commit 8c9d5bd

7 files changed

+136
-2
lines changed

CHANGELOG.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,65 @@
11
# Changelog
22

3+
## 2020.8.3 (31 August 2020)
4+
5+
### Enhancements
6+
7+
1. Add telemetry about the install source for the extension.
8+
9+
### Thanks
10+
11+
Thanks to the following projects which we fully rely on to provide some of
12+
our features:
13+
14+
- [debugpy](https://pypi.org/project/debugpy/)
15+
- [isort](https://pypi.org/project/isort/)
16+
- [jedi](https://pypi.org/project/jedi/)
17+
and [parso](https://pypi.org/project/parso/)
18+
- [Microsoft Python Language Server](https://github.com/microsoft/python-language-server)
19+
- [Pylance](https://github.com/microsoft/pylance-release)
20+
- [exuberant ctags](http://ctags.sourceforge.net/) (user-installed)
21+
- [rope](https://pypi.org/project/rope/) (user-installed)
22+
23+
Also thanks to the various projects we provide integrations with which help
24+
make this extension useful:
25+
26+
- Debugging support:
27+
[Django](https://pypi.org/project/Django/),
28+
[Flask](https://pypi.org/project/Flask/),
29+
[gevent](https://pypi.org/project/gevent/),
30+
[Jinja](https://pypi.org/project/Jinja/),
31+
[Pyramid](https://pypi.org/project/pyramid/),
32+
[PySpark](https://pypi.org/project/pyspark/),
33+
[Scrapy](https://pypi.org/project/Scrapy/),
34+
[Watson](https://pypi.org/project/Watson/)
35+
- Formatting:
36+
[autopep8](https://pypi.org/project/autopep8/),
37+
[black](https://pypi.org/project/black/),
38+
[yapf](https://pypi.org/project/yapf/)
39+
- Interpreter support:
40+
[conda](https://conda.io/),
41+
[direnv](https://direnv.net/),
42+
[pipenv](https://pypi.org/project/pipenv/),
43+
[pyenv](https://github.com/pyenv/pyenv),
44+
[venv](https://docs.python.org/3/library/venv.html#module-venv),
45+
[virtualenv](https://pypi.org/project/virtualenv/)
46+
- Linting:
47+
[bandit](https://pypi.org/project/bandit/),
48+
[flake8](https://pypi.org/project/flake8/),
49+
[mypy](https://pypi.org/project/mypy/),
50+
[prospector](https://pypi.org/project/prospector/),
51+
[pylint](https://pypi.org/project/pylint/),
52+
[pydocstyle](https://pypi.org/project/pydocstyle/),
53+
[pylama](https://pypi.org/project/pylama/)
54+
- Testing:
55+
[nose](https://pypi.org/project/nose/),
56+
[pytest](https://pypi.org/project/pytest/),
57+
[unittest](https://docs.python.org/3/library/unittest.html#module-unittest)
58+
59+
And finally thanks to the [Python](https://www.python.org/) development team and
60+
community for creating a fantastic programming language and community to be a
61+
part of!
62+
363
## 2020.8.2 (27 August 2020)
464

565
### Enhancements

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "python",
33
"displayName": "Python",
44
"description": "Linting, Debugging (multi-threaded, remote), Intellisense, Jupyter Notebooks, code formatting, refactoring, unit tests, snippets, and more.",
5-
"version": "2020.8.2",
5+
"version": "2020.8.3",
66
"featureFlags": {
77
"usingNewInterpreterStorage": true
88
},

src/client/extensionActivation.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { Commands, PYTHON, PYTHON_LANGUAGE, STANDARD_OUTPUT_CHANNEL, UseProposed
1717
import { registerTypes as installerRegisterTypes } from './common/installer/serviceRegistry';
1818
import { traceError } from './common/logger';
1919
import { registerTypes as platformRegisterTypes } from './common/platform/serviceRegistry';
20+
import { IFileSystem } from './common/platform/types';
2021
import { registerTypes as processRegisterTypes } from './common/process/serviceRegistry';
2122
import { registerTypes as commonRegisterTypes } from './common/serviceRegistry';
2223
import {
@@ -57,6 +58,7 @@ import { registerTypes as providersRegisterTypes } from './providers/serviceRegi
5758
import { activateSimplePythonRefactorProvider } from './providers/simpleRefactorProvider';
5859
import { TerminalProvider } from './providers/terminalProvider';
5960
import { ISortImportsEditingProvider } from './providers/types';
61+
import { setExtensionInstallTelemetryProperties } from './telemetry/extensionInstallTelemetry';
6062
import { registerTypes as commonRegisterTerminalTypes } from './terminals/serviceRegistry';
6163
import { ICodeExecutionManager, ITerminalAutoActivation } from './terminals/types';
6264
import { TEST_OUTPUT_CHANNEL } from './testing/common/constants';
@@ -104,6 +106,10 @@ async function activateLegacy(
104106
platformRegisterTypes(serviceManager);
105107
processRegisterTypes(serviceManager);
106108

109+
// We need to setup this property before any telemetry is sent
110+
const fs = serviceManager.get<IFileSystem>(IFileSystem);
111+
await setExtensionInstallTelemetryProperties(fs);
112+
107113
const applicationEnv = serviceManager.get<IApplicationEnvironment>(IApplicationEnvironment);
108114
const enableProposedApi = applicationEnv.packageJson.enableProposedApi;
109115
serviceManager.addSingletonInstance<boolean>(UseProposedApi, enableProposedApi);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
import * as path from 'path';
5+
import { setSharedProperty } from '.';
6+
import { IFileSystem } from '../common/platform/types';
7+
import { EXTENSION_ROOT_DIR } from '../constants';
8+
9+
/**
10+
* Sets shared telemetry property about where the extension was installed from
11+
* currently we only detect installations from the Python coding pack installer.
12+
* Those installations get the 'pythonCodingPack'. Otherwise assume the default
13+
* case as 'MarketPlace'.
14+
*
15+
*/
16+
export async function setExtensionInstallTelemetryProperties(fs: IFileSystem) {
17+
// Look for PythonCodingPack file under `%USERPROFILE%/.vscode/extensions`
18+
// folder. If that file exists treat this extension as installed from coding
19+
// pack.
20+
//
21+
// Use parent of EXTENSION_ROOT_DIR to access %USERPROFILE%/.vscode/extensions
22+
// this is because the installer will add PythonCodingPack to %USERPROFILE%/.vscode/extensions
23+
// or %USERPROFILE%/.vscode-insiders/extensions depending on what was installed
24+
// previously by the user. If we always join (<home>, .vscode, extensions), we will
25+
// end up looking at the wrong place, with respect to the extension that was launched.
26+
const fileToCheck = path.join(path.dirname(EXTENSION_ROOT_DIR), 'PythonCodingPack');
27+
if (await fs.fileExists(fileToCheck)) {
28+
setSharedProperty('installSource', 'pythonCodingPack');
29+
} else {
30+
// We did not file the `PythonCodingPack` file, assume market place install.
31+
setSharedProperty('installSource', 'marketPlace');
32+
}
33+
}

src/client/telemetry/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,12 @@ export interface ISharedPropertyMapping {
332332
* For every DS telemetry we would like to know the type of Notebook Editor used when doing something.
333333
*/
334334
['ds_notebookeditor']: undefined | 'old' | 'custom' | 'native';
335+
336+
/**
337+
* For every telemetry event from the extension we want to make sure we can associate it with install
338+
* source. We took this approach to work around very limiting query performance issues.
339+
*/
340+
['installSource']: undefined | 'marketPlace' | 'pythonCodingPack';
335341
}
336342

337343
// Map all events to their properties
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import * as assert from 'assert';
2+
import * as sinon from 'sinon';
3+
import { anyString, instance, mock, when } from 'ts-mockito';
4+
import { FileSystem } from '../../client/common/platform/fileSystem';
5+
import { IFileSystem } from '../../client/common/platform/types';
6+
import * as Telemetry from '../../client/telemetry';
7+
import { setExtensionInstallTelemetryProperties } from '../../client/telemetry/extensionInstallTelemetry';
8+
9+
suite('Extension Install Telemetry', () => {
10+
let fs: IFileSystem;
11+
let telemetryPropertyStub: sinon.SinonStub;
12+
setup(() => {
13+
fs = mock(FileSystem);
14+
telemetryPropertyStub = sinon.stub(Telemetry, 'setSharedProperty');
15+
});
16+
teardown(() => {
17+
telemetryPropertyStub.restore();
18+
});
19+
test('PythonCodingPack exists', async () => {
20+
when(fs.fileExists(anyString())).thenResolve(true);
21+
await setExtensionInstallTelemetryProperties(instance(fs));
22+
assert.ok(telemetryPropertyStub.calledOnceWithExactly('installSource', 'pythonCodingPack'));
23+
});
24+
test('PythonCodingPack does not exists', async () => {
25+
when(fs.fileExists(anyString())).thenResolve(false);
26+
await setExtensionInstallTelemetryProperties(instance(fs));
27+
assert.ok(telemetryPropertyStub.calledOnceWithExactly('installSource', 'marketPlace'));
28+
});
29+
});

0 commit comments

Comments
 (0)