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

Commit

Permalink
Merge pull request #169 from microsoft/users/t-anmah/simulation-depen…
Browse files Browse the repository at this point in the history
…dency-checker-fix

Users/t anmah/simulation dependency checker fix
  • Loading branch information
andreamah authored Jan 22, 2020
2 parents 0c56aca + 104e40e commit 33ad456
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 55 deletions.
22 changes: 10 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,15 @@ You will be prompted to install the Python dependencies during the first use.
- _**[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)
- _**[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.

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)
- Python Modules for Simulation
- **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.**
- Playsound : `pip install playsound`
- Pywin32 : `pip install pywin32`
- On Windows, you need to use the above command in the console to manually install pywin32.
- Python-Socketio : `pip install python-socketio`
- Requests : `pip install requests`
- Application Insights: `pip install applicationinsights`

- _**Playsound**_
install by typing the following commands in a console: `pip install playsound`

- _**Pywin 32**_
install by typing the following commands in a console (only for Windows computers, you must run it manually): `pip install pywin32`
- _**Python-Socketio**_
install by typing the following commands in a console: `pip install python-socketio`
- _**Requests**_
install by typing the following commands in a console: `pip install requests`
- _**Application Insights**_
install by typing the following commands in a console: `pip install applicationinsights`

## Useful Links
- Tutorials and Example Code for Adafruit CPX:
Expand Down Expand Up @@ -102,6 +98,8 @@ Before deploying the python code to your CPX device, you need to format your dev
2. Download the lastest version of the cpx library (link: https://learn.adafruit.com/welcome-to-circuitpython/circuitpython-libraries).
**_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)).

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`

<img alt="Deploy to Device" src=https://raw.githubusercontent.com/microsoft/vscode-python-devicesimulator/dev/assets/readmeFiles/deployToBoard.png>

### 5. Use the Serial Monitor for your Adafruit CPX device (available on Windows and Mac only)
Expand Down
28 changes: 11 additions & 17 deletions docs/developers-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,18 @@
- **NOTE :** Make sure pip is added to your environment variables as well
(for example it could be found at : `c:\users\<...>\appdata\local\programs\python\python37\lib\site-packages\pip`)
- Run in a console `python -m pip install --upgrade pip`

* Python Modules

- **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.
- Playsound
- Run the command in a console : `pip install playsound`
- Pytest
- Run the command in a console : `pip install pytest`
- Pywin32
- **Note:** This is only needed for Windows computers. You must install it manually with the above command!
- Run the command in a console : `pip install pywin32`
- Python-Socketio
- Run the command in a console : `pip install python-socketio`
- Requests
- Run the command in a console : `pip install requests`
- Application Insights
- Run the command in a console : `pip install applicationinsights`

- **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.
- pywin32 **(on Windows only)**
- On Windows, you need to use the following command in the console to manually install pywin32: `pip install pywin32`
- *playsound*
- *pytest*
- *python-socketio*
- *requests*
- *applicationinsights*

*italics*: used in simulation mode only
* VS Code

* Python extension for VS Code (download from VS Code market place)
Expand Down
19 changes: 11 additions & 8 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,18 @@ _Note: You need to install all the dependencies in order to use the extension._
_(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.)_
- [Python VS Code extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python)
- **Note:** This extension is installed automatically from the marketplace when you install our extension
- Python Modules
- **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.
- Playsound : `pip install playsound`
- Pywin32 : `pip install pywin32`
- **Note:** This is only needed for Windows computers. You must install it manually with the above command!
- Python-Socketio : `pip install python-socketio`
- Requests : `pip install requests`
- Application Insights: `pip install applicationinsights`

* Python Modules
- **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.**
- pywin32 **(on Windows only)**: `pip install pywin32`
- On Windows, you need to use the above command in the console to manually install pywin32.
- *playsound*: `pip install playsound`
- *pytest*: `pip install pytest`
- *python-socketio*: `pip install python-socketio`
- *requests*: `pip install requests`
- *applicationinsights*: `pip install applicationinsights`

*italics*: used in simulation mode only
## How to use the Extension

- [How to use the Extension](/docs/how-to-use.md)
4 changes: 2 additions & 2 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const languages = [{ folderName: "en", id: "en" }];
gulp.task("clean", () => {
return del(
[
"out/!(python_libs)",
"out/*",
"package.nls.*.json",
"../../dist/*0.0.0-UNTRACKEDVERSION.vsix"
],
Expand All @@ -36,7 +36,7 @@ gulp.task("clean", () => {
const pythonToMove = [
"./src/adafruit_circuitplayground/*.*",
"./src/*.py",
"./src/requirements.txt"
"./src/requirements.txt",
];

gulp.task("python-compile", () => {
Expand Down
1 change: 1 addition & 0 deletions locales/en/out/constants.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"dialogResponses.installNow": "Install Now",
"dialogResponses.dontInstall": "Don't Install",
"dialogResponses.tutorials": "Tutorials on Adafruit",
"dialogResponses.readInstall": "Read installation docs",
"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.",
"error.debuggingSessionInProgress": "[ERROR] A debugging session is currently in progress, please stop it before running your code. \n",
"error.incorrectFileNameForDevice": "[ERROR] Can\\'t deploy to your Circuit Playground Express device, please rename your file to \"code.py\" or \"main.py\". \n",
Expand Down
10 changes: 10 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export const CONSTANTS = {
"error.debuggingSessionInProgress",
"[ERROR] A debugging session is currently in progress, please stop it before running your code. \n"
),
DEPENDENCY_DOWNLOAD_ERROR:
"Package downloads failed. Some functionalities may not work. Try restarting the simulator or review the installation docs.",
FAILED_TO_OPEN_SERIAL_PORT: (port: string): string => {
return localize(
"error.failedToOpenSerialPort",
Expand Down Expand Up @@ -101,6 +103,10 @@ export const CONSTANTS = {
"Webview sent an unexpected message"
)
},
FILESYSTEM: {
OUTPUT_DIRECTORY: "out",
PYTHON_LIBS_DIR: "python_libs"
},
INFO: {
ARE_YOU_SURE: localize(
"info.areYouSure",
Expand Down Expand Up @@ -203,6 +209,7 @@ export const CONSTANTS = {
"https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground/tree/master/examples",
HELP:
"https://learn.adafruit.com/adafruit-circuit-playground-express/circuitpython-quickstart",
INSTALL: "https://github.com/microsoft/vscode-python-devicesimulator/blob/dev/docs/install.md",
PRIVACY: "https://www.adafruit.com/privacy",
TUTORIALS:
"https://learn.adafruit.com/circuitpython-made-easy-on-circuit-playground-express/circuit-playground-express-library"
Expand Down Expand Up @@ -359,6 +366,9 @@ export namespace DialogResponses {
export const YES: MessageItem = {
title: localize("dialogResponses.Yes", "Yes")
};
export const READ_INSTALL_MD: MessageItem = {
title: localize("dialogResponses.readInstall", "Read installation docs")
};
}

export const CPX_CONFIG_FILE = path.join(".vscode", "cpx.json");
Expand Down
6 changes: 3 additions & 3 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export async function activate(context: vscode.ExtensionContext) {
{
// Only allow the webview to access resources in our extension's media directory
localResourceRoots: [
vscode.Uri.file(path.join(context.extensionPath, "out"))
vscode.Uri.file(path.join(context.extensionPath, CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY))
],
enableScripts: true
}
Expand Down Expand Up @@ -412,7 +412,7 @@ export async function activate(context: vscode.ExtensionContext) {
currentPanel.webview.postMessage({ command: "activate-play" });

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

const deviceProcess = cp.spawn(pythonExecutableName, [
utils.getPathToScript(context, "out", "device.py"),
utils.getPathToScript(context, CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY, "device.py"),
currentFileAbsPath
]);

Expand Down
36 changes: 24 additions & 12 deletions src/extension_utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import { CPXWorkspace } from "../cpxWorkspace";
import * as cp from "child_process";
import * as util from "util";
import * as open from "open";
const exec = util.promisify(cp.exec);

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

export const checkPythonDependencies = async (context: vscode.ExtensionContext, pythonExecutable: string) => {
let hasInstalledDependencies: boolean = false;
const pathToLibs: string = getPathToScript(context, CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY, CONSTANTS.FILESYSTEM.PYTHON_LIBS_DIR);
if (checkPipDependency() && checkPythonDependency()) {
if (checkConfig(CONFIG.SHOW_DEPENDENCY_INSTALL)) {
hasInstalledDependencies = await promptInstallPythonDependencies(context, pythonExecutable);
if (hasInstalledDependencies) {
await vscode.workspace
.getConfiguration()
.update(CONFIG.SHOW_DEPENDENCY_INSTALL, false);
}
// check if ./out/python_libs exists; if not, the dependencies
// for adafruit_circuitpython are not (successfully) installed yet
hasInstalledDependencies = fs.existsSync(pathToLibs) || await promptInstallPythonDependencies(context, pythonExecutable, pathToLibs);
}
} else {
hasInstalledDependencies = false;
}
return hasInstalledDependencies;
};

export const promptInstallPythonDependencies = (context: vscode.ExtensionContext, pythonExecutable: string) => {
export const promptInstallPythonDependencies = (context: vscode.ExtensionContext, pythonExecutable: string, pathToLibs: string) => {
return vscode.window.showInformationMessage(
CONSTANTS.INFO.INSTALL_PYTHON_DEPENDENCIES,
DialogResponses.YES,
DialogResponses.NO)
.then((selection: vscode.MessageItem | undefined) => {
if (selection === DialogResponses.YES) {
return installPythonDependencies(context, pythonExecutable);
return installPythonDependencies(context, pythonExecutable, pathToLibs);
} else if (selection === DialogResponses.NO) {
return vscode.window.showInformationMessage(
CONSTANTS.INFO.ARE_YOU_SURE,
DialogResponses.INSTALL_NOW,
DialogResponses.DONT_INSTALL
).then((installChoice: vscode.MessageItem | undefined) => {
if (installChoice === DialogResponses.INSTALL_NOW) {
return installPythonDependencies(context, pythonExecutable);
return installPythonDependencies(context, pythonExecutable, pathToLibs);
} else {
return false;
}
Expand All @@ -302,17 +301,30 @@ export const getTelemetryState = () => {
.get("telemetry.enableTelemetry", true);
};

export const installPythonDependencies = async (context: vscode.ExtensionContext, pythonExecutable: string) => {
export const installPythonDependencies = async (context: vscode.ExtensionContext, pythonExecutable: string, pathToLibs: string) => {
let installed: boolean = false;
try {
vscode.window.showInformationMessage(CONSTANTS.INFO.INSTALLING_PYTHON_DEPENDENCIES);
const requirementsPath: string = getPathToScript(context, "out", "requirements.txt");
const pathToLibs: string = getPathToScript(context, "out", "python_libs");

const requirementsPath: string = getPathToScript(context, CONSTANTS.FILESYSTEM.OUTPUT_DIRECTORY, "requirements.txt");

// run command to download dependencies to out/python_libs
const { stdout } = await exec(`${pythonExecutable} -m pip install -r ${requirementsPath} -t ${pathToLibs}`);
console.info(stdout);
installed = true;

vscode.window.showInformationMessage(CONSTANTS.INFO.SUCCESSFUL_INSTALL);
} catch (err) {

vscode.window
.showErrorMessage(CONSTANTS.ERROR.DEPENDENCY_DOWNLOAD_ERROR,
DialogResponses.READ_INSTALL_MD)
.then((selection: vscode.MessageItem | undefined) => {
if (selection === DialogResponses.READ_INSTALL_MD) {
open(CONSTANTS.LINKS.INSTALL);
}
});

console.error(err);
installed = false;
}
Expand Down
2 changes: 1 addition & 1 deletion src/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ pytest==5.0.1
applicationinsights==0.11.9
python-socketio==4.3.1
requests==2.22.0
pywin32==224
pywin32==227; platform_system == "Windows"

0 comments on commit 33ad456

Please sign in to comment.