Skip to content
This repository was archived by the owner on Dec 23, 2021. It is now read-only.

Commit 33ad456

Browse files
authored
Merge pull request #169 from microsoft/users/t-anmah/simulation-dependency-checker-fix
Users/t anmah/simulation dependency checker fix
2 parents 0c56aca + 104e40e commit 33ad456

File tree

9 files changed

+73
-55
lines changed

9 files changed

+73
-55
lines changed

README.md

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,15 @@ You will be prompted to install the Python dependencies during the first use.
4343
- _**[Python 3.7.4](https://www.python.org/downloads/)**_: Make sure you've added python and pip to your PATH in your environment variables. (1)
4444
- _**[Python VS Code extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python)**_: This will be installed automatically from the marketplace when you install Device Simulator Express.
4545

46-
The following dependecies can be installed for you by the extension by clicking yes when you are prompted to (**except** `pywin32` which is needed only on Windows platform). (2)
46+
- Python Modules for Simulation
47+
- **Note:** On extension activation, you will be prompted with a popup message asking if you want the modules to be automatically installed for you. The following Python modules should be downloaded when you select "yes" on the prompt message. **If modules are not installed correctly, please use the "pip install" commands listed below.**
48+
- Playsound : `pip install playsound`
49+
- Pywin32 : `pip install pywin32`
50+
- On Windows, you need to use the above command in the console to manually install pywin32.
51+
- Python-Socketio : `pip install python-socketio`
52+
- Requests : `pip install requests`
53+
- Application Insights: `pip install applicationinsights`
4754

48-
- _**Playsound**_
49-
install by typing the following commands in a console: `pip install playsound`
50-
51-
- _**Pywin 32**_
52-
install by typing the following commands in a console (only for Windows computers, you must run it manually): `pip install pywin32`
53-
- _**Python-Socketio**_
54-
install by typing the following commands in a console: `pip install python-socketio`
55-
- _**Requests**_
56-
install by typing the following commands in a console: `pip install requests`
57-
- _**Application Insights**_
58-
install by typing the following commands in a console: `pip install applicationinsights`
5955

6056
## Useful Links
6157
- Tutorials and Example Code for Adafruit CPX:
@@ -102,6 +98,8 @@ Before deploying the python code to your CPX device, you need to format your dev
10298
2. Download the lastest version of the cpx library (link: https://learn.adafruit.com/welcome-to-circuitpython/circuitpython-libraries).
10399
**_Note:_** Make sure you name your file `main.py` or `code.py`: the device automatically runs the first file that is likely named. This is the convention for CircuitPython ([source](https://learn.adafruit.com/welcome-to-circuitpython/creating-and-editing-code#naming-your-program-file-7-32)).
104100

101+
Then, if you are on Windows, you will also need to install the Python Pywin32 package. Use the following command in the console: `pip install pywin32`
102+
105103
<img alt="Deploy to Device" src=https://raw.githubusercontent.com/microsoft/vscode-python-devicesimulator/dev/assets/readmeFiles/deployToBoard.png>
106104

107105
### 5. Use the Serial Monitor for your Adafruit CPX device (available on Windows and Mac only)

docs/developers-setup.md

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,18 @@
1313
- **NOTE :** Make sure pip is added to your environment variables as well
1414
(for example it could be found at : `c:\users\<...>\appdata\local\programs\python\python37\lib\site-packages\pip`)
1515
- Run in a console `python -m pip install --upgrade pip`
16-
16+
1717
* Python Modules
18-
19-
- **Note:** On extension activation you will be prompted a popup asking if you want the modules to be automatically installed for you, **except** `pywin32` which is needed only on Windows platform.
20-
- Playsound
21-
- Run the command in a console : `pip install playsound`
22-
- Pytest
23-
- Run the command in a console : `pip install pytest`
24-
- Pywin32
25-
- **Note:** This is only needed for Windows computers. You must install it manually with the above command!
26-
- Run the command in a console : `pip install pywin32`
27-
- Python-Socketio
28-
- Run the command in a console : `pip install python-socketio`
29-
- Requests
30-
- Run the command in a console : `pip install requests`
31-
- Application Insights
32-
- Run the command in a console : `pip install applicationinsights`
33-
18+
- **Note:** On extension activation, you will be prompted with a popup asking if you want the modules to be automatically installed for you. The following python modules should be downloaded when you select "yes" on the prompt message.
19+
- pywin32 **(on Windows only)**
20+
- On Windows, you need to use the following command in the console to manually install pywin32: `pip install pywin32`
21+
- *playsound*
22+
- *pytest*
23+
- *python-socketio*
24+
- *requests*
25+
- *applicationinsights*
26+
27+
*italics*: used in simulation mode only
3428
* VS Code
3529

3630
* Python extension for VS Code (download from VS Code market place)

docs/install.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,18 @@ _Note: You need to install all the dependencies in order to use the extension._
2222
_(Note: the easiest way to do it might be when you install Python, you can select the "Add to PATH" option directly. Otherwise you can search how to insert it manually, but make sure that when you type `python` (or `python3.7`) in a terminal, the command is recognized.)_
2323
- [Python VS Code extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python)
2424
- **Note:** This extension is installed automatically from the marketplace when you install our extension
25-
- Python Modules
26-
- **Note:** On extension activation a popup will be prompted asking if you want the modules to be automatically installed for you, **except** `pywin32` which is needed only on Windows platform.
27-
- Playsound : `pip install playsound`
28-
- Pywin32 : `pip install pywin32`
29-
- **Note:** This is only needed for Windows computers. You must install it manually with the above command!
30-
- Python-Socketio : `pip install python-socketio`
31-
- Requests : `pip install requests`
32-
- Application Insights: `pip install applicationinsights`
25+
26+
* Python Modules
27+
- **Note:** On extension activation, you will be prompted with a popup asking if you want the modules to be automatically installed for you. The following python modules should be downloaded when you select "yes" on the prompt message. **If modules are not installed correctly, please use the "pip install" commands listed below.**
28+
- pywin32 **(on Windows only)**: `pip install pywin32`
29+
- On Windows, you need to use the above command in the console to manually install pywin32.
30+
- *playsound*: `pip install playsound`
31+
- *pytest*: `pip install pytest`
32+
- *python-socketio*: `pip install python-socketio`
33+
- *requests*: `pip install requests`
34+
- *applicationinsights*: `pip install applicationinsights`
3335

36+
*italics*: used in simulation mode only
3437
## How to use the Extension
3538

3639
- [How to use the Extension](/docs/how-to-use.md)

gulpfile.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const languages = [{ folderName: "en", id: "en" }];
2525
gulp.task("clean", () => {
2626
return del(
2727
[
28-
"out/!(python_libs)",
28+
"out/*",
2929
"package.nls.*.json",
3030
"../../dist/*0.0.0-UNTRACKEDVERSION.vsix"
3131
],
@@ -36,7 +36,7 @@ gulp.task("clean", () => {
3636
const pythonToMove = [
3737
"./src/adafruit_circuitplayground/*.*",
3838
"./src/*.py",
39-
"./src/requirements.txt"
39+
"./src/requirements.txt",
4040
];
4141

4242
gulp.task("python-compile", () => {

locales/en/out/constants.i18n.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"dialogResponses.installNow": "Install Now",
1010
"dialogResponses.dontInstall": "Don't Install",
1111
"dialogResponses.tutorials": "Tutorials on Adafruit",
12+
"dialogResponses.readInstall": "Read installation docs",
1213
"error.debuggerServerInitFailed": "Warning : The Debugger Server cannot be opened. Please try to free the port {0} if it's already in use or select another one in your Settings 'Device Simulator Express: Debugger Server Port' and start another debug session.\n You can still debug your code but you won't be able to use the Simulator.",
1314
"error.debuggingSessionInProgress": "[ERROR] A debugging session is currently in progress, please stop it before running your code. \n",
1415
"error.incorrectFileNameForDevice": "[ERROR] Can\\'t deploy to your Circuit Playground Express device, please rename your file to \"code.py\" or \"main.py\". \n",

src/constants.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ export const CONSTANTS = {
4545
"error.debuggingSessionInProgress",
4646
"[ERROR] A debugging session is currently in progress, please stop it before running your code. \n"
4747
),
48+
DEPENDENCY_DOWNLOAD_ERROR:
49+
"Package downloads failed. Some functionalities may not work. Try restarting the simulator or review the installation docs.",
4850
FAILED_TO_OPEN_SERIAL_PORT: (port: string): string => {
4951
return localize(
5052
"error.failedToOpenSerialPort",
@@ -101,6 +103,10 @@ export const CONSTANTS = {
101103
"Webview sent an unexpected message"
102104
)
103105
},
106+
FILESYSTEM: {
107+
OUTPUT_DIRECTORY: "out",
108+
PYTHON_LIBS_DIR: "python_libs"
109+
},
104110
INFO: {
105111
ARE_YOU_SURE: localize(
106112
"info.areYouSure",
@@ -203,6 +209,7 @@ export const CONSTANTS = {
203209
"https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/tree/master/examples",
204210
HELP:
205211
"https://learn.adafruit.com/adafruit-circuit-playground-express/circuitpython-quickstart",
212+
INSTALL: "https://github.com/microsoft/vscode-python-devicesimulator/blob/dev/docs/install.md",
206213
PRIVACY: "https://www.adafruit.com/privacy",
207214
TUTORIALS:
208215
"https://learn.adafruit.com/circuitpython-made-easy-on-circuit-playground-express/circuit-playground-express-library"
@@ -359,6 +366,9 @@ export namespace DialogResponses {
359366
export const YES: MessageItem = {
360367
title: localize("dialogResponses.Yes", "Yes")
361368
};
369+
export const READ_INSTALL_MD: MessageItem = {
370+
title: localize("dialogResponses.readInstall", "Read installation docs")
371+
};
362372
}
363373

364374
export const CPX_CONFIG_FILE = path.join(".vscode", "cpx.json");

src/extension.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export async function activate(context: vscode.ExtensionContext) {
108108
{
109109
// Only allow the webview to access resources in our extension's media directory
110110
localResourceRoots: [
111-
vscode.Uri.file(path.join(context.extensionPath, "out"))
111+
vscode.Uri.file(path.join(context.extensionPath, CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY))
112112
],
113113
enableScripts: true
114114
}
@@ -412,7 +412,7 @@ export async function activate(context: vscode.ExtensionContext) {
412412
currentPanel.webview.postMessage({ command: "activate-play" });
413413

414414
childProcess = cp.spawn(pythonExecutableName, [
415-
utils.getPathToScript(context, "out", "process_user_code.py"),
415+
utils.getPathToScript(context, CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY, "process_user_code.py"),
416416
currentFileAbsPath,
417417
JSON.stringify({ enable_telemetry: utils.getTelemetryState() })
418418
]);
@@ -549,7 +549,7 @@ export async function activate(context: vscode.ExtensionContext) {
549549
);
550550

551551
const deviceProcess = cp.spawn(pythonExecutableName, [
552-
utils.getPathToScript(context, "out", "device.py"),
552+
utils.getPathToScript(context, CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY, "device.py"),
553553
currentFileAbsPath
554554
]);
555555

src/extension_utils/utils.ts

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
import { CPXWorkspace } from "../cpxWorkspace";
1919
import * as cp from "child_process";
2020
import * as util from "util";
21+
import * as open from "open";
2122
const exec = util.promisify(cp.exec);
2223

2324
// tslint:disable-next-line: export-name
@@ -258,37 +259,35 @@ export const checkConfig = (configName: string): boolean => {
258259

259260
export const checkPythonDependencies = async (context: vscode.ExtensionContext, pythonExecutable: string) => {
260261
let hasInstalledDependencies: boolean = false;
262+
const pathToLibs: string = getPathToScript(context, CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY, CONSTANTS.FILESYSTEM.PYTHON_LIBS_DIR);
261263
if (checkPipDependency() && checkPythonDependency()) {
262264
if (checkConfig(CONFIG.SHOW_DEPENDENCY_INSTALL)) {
263-
hasInstalledDependencies = await promptInstallPythonDependencies(context, pythonExecutable);
264-
if (hasInstalledDependencies) {
265-
await vscode.workspace
266-
.getConfiguration()
267-
.update(CONFIG.SHOW_DEPENDENCY_INSTALL, false);
268-
}
265+
// check if ./out/python_libs exists; if not, the dependencies
266+
// for adafruit_circuitpython are not (successfully) installed yet
267+
hasInstalledDependencies = fs.existsSync(pathToLibs) || await promptInstallPythonDependencies(context, pythonExecutable, pathToLibs);
269268
}
270269
} else {
271270
hasInstalledDependencies = false;
272271
}
273272
return hasInstalledDependencies;
274273
};
275274

276-
export const promptInstallPythonDependencies = (context: vscode.ExtensionContext, pythonExecutable: string) => {
275+
export const promptInstallPythonDependencies = (context: vscode.ExtensionContext, pythonExecutable: string, pathToLibs: string) => {
277276
return vscode.window.showInformationMessage(
278277
CONSTANTS.INFO.INSTALL_PYTHON_DEPENDENCIES,
279278
DialogResponses.YES,
280279
DialogResponses.NO)
281280
.then((selection: vscode.MessageItem | undefined) => {
282281
if (selection === DialogResponses.YES) {
283-
return installPythonDependencies(context, pythonExecutable);
282+
return installPythonDependencies(context, pythonExecutable, pathToLibs);
284283
} else if (selection === DialogResponses.NO) {
285284
return vscode.window.showInformationMessage(
286285
CONSTANTS.INFO.ARE_YOU_SURE,
287286
DialogResponses.INSTALL_NOW,
288287
DialogResponses.DONT_INSTALL
289288
).then((installChoice: vscode.MessageItem | undefined) => {
290289
if (installChoice === DialogResponses.INSTALL_NOW) {
291-
return installPythonDependencies(context, pythonExecutable);
290+
return installPythonDependencies(context, pythonExecutable, pathToLibs);
292291
} else {
293292
return false;
294293
}
@@ -302,17 +301,30 @@ export const getTelemetryState = () => {
302301
.get("telemetry.enableTelemetry", true);
303302
};
304303

305-
export const installPythonDependencies = async (context: vscode.ExtensionContext, pythonExecutable: string) => {
304+
export const installPythonDependencies = async (context: vscode.ExtensionContext, pythonExecutable: string, pathToLibs: string) => {
306305
let installed: boolean = false;
307306
try {
308307
vscode.window.showInformationMessage(CONSTANTS.INFO.INSTALLING_PYTHON_DEPENDENCIES);
309-
const requirementsPath: string = getPathToScript(context, "out", "requirements.txt");
310-
const pathToLibs: string = getPathToScript(context, "out", "python_libs");
308+
309+
const requirementsPath: string = getPathToScript(context, CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY, "requirements.txt");
310+
311+
// run command to download dependencies to out/python_libs
311312
const { stdout } = await exec(`${pythonExecutable} -m pip install -r ${requirementsPath} -t ${pathToLibs}`);
312313
console.info(stdout);
313314
installed = true;
315+
314316
vscode.window.showInformationMessage(CONSTANTS.INFO.SUCCESSFUL_INSTALL);
315317
} catch (err) {
318+
319+
vscode.window
320+
.showErrorMessage(CONSTANTS.ERROR.DEPENDENCY_DOWNLOAD_ERROR,
321+
DialogResponses.READ_INSTALL_MD)
322+
.then((selection: vscode.MessageItem | undefined) => {
323+
if (selection === DialogResponses.READ_INSTALL_MD) {
324+
open(CONSTANTS.LINKS.INSTALL);
325+
}
326+
});
327+
316328
console.error(err);
317329
installed = false;
318330
}

src/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ pytest==5.0.1
33
applicationinsights==0.11.9
44
python-socketio==4.3.1
55
requests==2.22.0
6-
pywin32==224
6+
pywin32==227; platform_system == "Windows"

0 commit comments

Comments
 (0)