Skip to content

Commit 0acc16e

Browse files
authored
Merge pull request #131 from paulober/develop
Patch v3.2.5
2 parents 5dbe697 + a84957a commit 0acc16e

30 files changed

+1115
-267
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ All notable changes to the "MicroPico" extension will be documented in this file
99

1010
---
1111

12+
## [3.2.5] - 2023-09-04
13+
14+
# Changed
15+
- Updated stubs to v1.20.0-441 unstable
16+
- Minimum VS Code version is now v1.81.1
17+
- Updated dependencies
18+
- Added official Python extension as dependency
19+
1220
## [3.2.4] - 2023-08-16
1321

1422
# Changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
"MicroPico" is a Visual Studio Code extension designed to simplify and accelerate the development of MicroPython projects for the Raspberry Pi Pico and Pico W boards. This tool streamlines the coding process, providing code highlighting, auto-completion, code snippets, and project management features, all tailored for the seamless development experience with MicroPython on Raspberry Pi Pico and Pico W microcontrollers.
66

7-
> __Auto-completion based on Raspberry Pi Pico W MicroPython firmware: [rp2-pico-w-20230426-v1.20.0.uf2](https://micropython.org/resources/firmware/rp2-pico-w-20230426-v1.20.0.uf2)__
7+
> __Auto-completion based on Raspberry Pi Pico W MicroPython firmware: [RPI_PICO_W-20230904-unstable-v1.20.0-441-gbf35eefc6.uf2](https://micropython.org/resources/firmware/RPI_PICO_W-20230904-unstable-v1.20.0-441-gbf35eefc6.uf2)__
88
99
Works with:
1010
| Platform | x64 | arm64 | armhf |

package-lock.json

Lines changed: 174 additions & 159 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "pico-w-go",
33
"displayName": "MicroPico",
44
"description": "Auto-completion, remote workspace and a REPL console integration for the Raspberry Pi Pico (W) with MicroPython firmware.",
5-
"version": "3.2.4",
5+
"version": "3.2.5",
66
"publisher": "paulober",
77
"license": "MPL-2.0",
88
"homepage": "https://github.com/paulober/MicroPico/blob/main/README.md",
@@ -20,7 +20,7 @@
2020
},
2121
"markdown": "github",
2222
"engines": {
23-
"vscode": "^1.76.0",
23+
"vscode": "^1.81.1",
2424
"node": ">=16.17.1"
2525
},
2626
"keywords": [
@@ -62,6 +62,9 @@
6262
"arm64",
6363
"arm"
6464
],
65+
"extensionDependencies": [
66+
"ms-python.python"
67+
],
6568
"minimumNodeVersion": 16,
6669
"contributes": {
6770
"commands": [
@@ -508,28 +511,29 @@
508511
},
509512
"devDependencies": {
510513
"@rollup/plugin-commonjs": "^25.0.4",
511-
"@rollup/plugin-node-resolve": "^15.1.0",
514+
"@rollup/plugin-node-resolve": "^15.2.1",
512515
"@rollup/plugin-terser": "^0.4.3",
513-
"@rollup/plugin-typescript": "^11.1.2",
516+
"@rollup/plugin-typescript": "^11.1.3",
514517
"@types/fs-extra": "^11.0.1",
515518
"@types/lodash": "^4.14.197",
516519
"@types/mocha": "^10.0.1",
517520
"@types/node": "^16.x",
518-
"@types/uuid": "^9.0.2",
519-
"@types/vscode": "^1.76.0",
520-
"@typescript-eslint/eslint-plugin": "^6.4.0",
521-
"@typescript-eslint/parser": "^6.4.0",
521+
"@types/uuid": "^9.0.3",
522+
"@types/vscode": "^1.81.0",
523+
"@typescript-eslint/eslint-plugin": "^6.5.0",
524+
"@typescript-eslint/parser": "^6.5.0",
522525
"@vscode/test-electron": "^2.3.4",
523-
"eslint": "^8.47.0",
526+
"eslint": "^8.48.0",
524527
"eslint-config-prettier": "^9.0.0",
525528
"glob": "^9.3.4",
526529
"mocha": "^10.2.0",
527-
"rollup": "^3.28.0",
528-
"rollup-plugin-copy": "^3.4.0",
529-
"typescript": "^5.1.6"
530+
"rollup": "^3.28.1",
531+
"rollup-plugin-copy": "^3.5.0",
532+
"typescript": "^5.2.2"
530533
},
531534
"dependencies": {
532535
"@paulober/pyboard-serial-com": "^1.5.3",
536+
"@vscode/python-extension": "^1.0.4",
533537
"fs-extra": "^11.1.1",
534538
"lodash": "^4.17.21",
535539
"rimraf": "^5.0.1",

rollup.config.mjs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ export default {
2121
plugins: [
2222
copy({
2323
targets: [
24-
{ src: 'node_modules/@paulober/pyboard-serial-com/scripts', dest: 'dist/' },
24+
{
25+
src: 'node_modules/@paulober/pyboard-serial-com/scripts',
26+
dest: 'dist/'
27+
},
2528
],
2629
}),
2730
nodeResolve({

src/activator.mts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,17 @@ export default class Activator {
4949
context: vscode.ExtensionContext
5050
): Promise<UI | undefined> {
5151
const settings = new Settings(context.workspaceState);
52-
const pyCommand = settings.pythonExecutable ?? (await getPythonCommand());
53-
settings.pythonExecutable = pyCommand;
52+
const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
53+
const pyCommands =
54+
(settings.pythonExecutable ? [settings.pythonExecutable] : undefined) ??
55+
(await getPythonCommand(workspaceFolder?.uri)).path ??
56+
[];
5457

55-
if (pyCommand === undefined) {
58+
if (pyCommands.length === 0) {
5659
const choice = await vscode.window.showErrorMessage(
57-
"Python3 is not installed or not in the system's PATH. Alernatively " +
60+
"Python3 is not installed or not in the system's PATH. " +
61+
"You can select a python installation thought the " +
62+
"vscode Python Extension. Alernatively " +
5863
"you can set the pythonPath setting to the path of your " +
5964
"Python3 executable in the settings.",
6065
"Open Settings"
@@ -66,9 +71,9 @@ export default class Activator {
6671

6772
return;
6873
}
74+
settings.pythonExecutable = pyCommands[0];
6975

70-
const isInstalled = await installPyserial(pyCommand);
71-
76+
const isInstalled = await installPyserial(settings.pythonExecutable);
7277
if (!isInstalled) {
7378
this.logger.error("Failed to install pyserial pip package.");
7479
void vscode.window.showErrorMessage(
@@ -102,9 +107,8 @@ export default class Activator {
102107
"No COM device found. Please check your connection or ports and " +
103108
"try again. Alternatively you can set the manualComDevice " +
104109
"setting to the path of your COM device in the settings but " +
105-
"make sure to deactivate autoConnect. For Linux users: make " +
106-
"sure your user is in dialout group: " +
107-
"sudo usermod -a -G dialout $USER",
110+
"make sure to deactivate autoConnect. For Linux users: check you " +
111+
"sufficient permission to access the device file of the Pico.",
108112
"Open Settings"
109113
)
110114
.then((choice: "Open Settings" | undefined) => {
@@ -121,7 +125,7 @@ export default class Activator {
121125
this.comDevice ?? "default",
122126
this.pyboardOnError.bind(this),
123127
this.pyboardOnExit.bind(this),
124-
pyCommand
128+
settings.pythonExecutable
125129
);
126130

127131
this.setupAutoConnect(settings);

src/osHelper.mts

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,43 @@
1+
import {
2+
PythonExtension,
3+
type ResolvedEnvironment,
4+
} from "@vscode/python-extension";
15
import { exec } from "child_process";
26
import { readFile, stat, writeFile } from "fs/promises";
3-
import { platform } from "os";
7+
import type { Uri } from "vscode";
8+
import { resolveVariables } from "./settings.mjs";
49

5-
const pythonCommands = {
6-
win32: "python.exe",
7-
darwin: "python3",
8-
linux: "python3",
9-
};
10-
11-
export async function getPythonCommand(): Promise<string | undefined> {
12-
const system = platform();
13-
let currentPlatform: keyof typeof pythonCommands;
10+
export interface IInterpreterDetails {
11+
path?: string[];
12+
resource?: Uri;
13+
}
1414

15-
if (system in pythonCommands) {
16-
currentPlatform = system as keyof typeof pythonCommands;
17-
} else {
18-
console.error(`Unsupported platform: ${system}`);
15+
function checkVersion(environment: ResolvedEnvironment): boolean {
16+
const version = environment.version;
1917

20-
return undefined;
18+
if (version?.major === 3 && version?.minor >= 9) {
19+
return true;
2120
}
2221

23-
const pythonCommand: string | undefined = pythonCommands[currentPlatform];
22+
return false;
23+
}
2424

25-
return new Promise(resolve => {
26-
exec(
27-
`${pythonCommand} --version`,
28-
{ timeout: 2500 },
29-
(error, stdout, stderr) => {
30-
if (error) {
31-
console.error(`Error executing ${pythonCommand}: ${error.message}`);
32-
resolve(undefined);
33-
} else {
34-
console.debug(`Python version: ${stdout || stderr}`);
35-
resolve(pythonCommand);
36-
}
37-
}
38-
);
39-
});
25+
export async function getPythonCommand(
26+
resource?: Uri
27+
): Promise<IInterpreterDetails> {
28+
const pyApi: PythonExtension = await PythonExtension.api();
29+
30+
const environment = await pyApi.environments.resolveEnvironment(
31+
pyApi.environments.getActiveEnvironmentPath(resource)
32+
);
33+
if (environment?.executable.uri && checkVersion(environment)) {
34+
return {
35+
path: resolveVariables([environment.executable.uri.fsPath], resource),
36+
resource,
37+
};
38+
}
39+
40+
return { path: undefined, resource };
4041
}
4142

4243
export async function pathExists(path: string): Promise<boolean> {

src/settings.mts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import type { Memento, WorkspaceConfiguration } from "vscode";
2-
import { window, workspace } from "vscode";
1+
import type { Memento, Uri, WorkspaceConfiguration } from "vscode";
2+
import { window, workspace as vsWorkspace } from "vscode";
33
import { PyboardRunner } from "@paulober/pyboard-serial-com";
44
import { extName, getProjectPath } from "./api.mjs";
55
import { join, relative } from "path";
@@ -27,7 +27,7 @@ export default class Settings {
2727
public pythonExecutable?: string;
2828

2929
constructor(context: Memento) {
30-
this.config = workspace.getConfiguration(extName);
30+
this.config = vsWorkspace.getConfiguration(extName);
3131

3232
this.context = context;
3333
this.pythonExecutable = this.getString(SettingsKey.pythonPath);
@@ -198,3 +198,33 @@ export default class Settings {
198198
return this.getArray(SettingsKey.pyIgnore) || [];
199199
}
200200
}
201+
202+
/**
203+
* Resolve vscode variables like ${workspaceFolder} in the given value.
204+
*
205+
* @param value Input
206+
* @param workspace The current workspace
207+
* @returns The resolved value
208+
*/
209+
export function resolveVariables(value: string[], workspace?: Uri): string[] {
210+
const substitutions = new Map<string, string>();
211+
const home = process.env.HOME || process.env.USERPROFILE;
212+
if (home) {
213+
substitutions.set("${userHome}", home);
214+
}
215+
if (workspace) {
216+
substitutions.set("${workspaceFolder}", workspace.fsPath);
217+
}
218+
substitutions.set("${cwd}", process.cwd());
219+
(vsWorkspace.workspaceFolders ?? []).forEach(w => {
220+
substitutions.set("${workspaceFolder:" + w.name + "}", w.uri.fsPath);
221+
});
222+
223+
return value.map(s => {
224+
for (const [key, value] of substitutions) {
225+
s = s.replace(key, value);
226+
}
227+
228+
return s;
229+
});
230+
}

src/terminal.mts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ const DEL = (count: number): string => `\x1b[${count}D\x1b[1P`;
77
// Ctrl+D; Ctrl+E
88
const IGNORED_CHARS = ["\x04", "\x05"];
99

10+
/**
11+
* A pseudo terminal (aka vREPL) so the serial connection can be used by
12+
* other parts of the extension while the user isn't executing a command in the REPL.
13+
*/
1014
export class Terminal implements Pseudoterminal {
1115
private openingMessageCallback: () => Promise<string>;
1216

stubs/stdlib/platform.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from uplatform import *

0 commit comments

Comments
 (0)