diff --git a/source/vscode/package.json b/source/vscode/package.json index 27ee7290846..c60a575948c 100644 --- a/source/vscode/package.json +++ b/source/vscode/package.json @@ -485,7 +485,7 @@ "notebook/cell/title": [ { "command": "qsharp-vscode.learningNotebookExplain", - "when": "notebookType == 'jupyter-notebook' && qsharp-vscode.learningWorkspaceDetected", + "when": "qsharp-vscode.learningNotebookActive", "group": "inline/cell@50" } ], diff --git a/source/vscode/src/learning/python/environment.ts b/source/vscode/src/learning/python/environment.ts index 4737fc767e1..5ec5a715ce4 100644 --- a/source/vscode/src/learning/python/environment.ts +++ b/source/vscode/src/learning/python/environment.ts @@ -10,6 +10,12 @@ import type { import { PythonEnvironments } from "@vscode/python-environments"; import * as vscode from "vscode"; +/** + * Dotted Python module name. Import checks come from author-supplied + * `course.json`, and reach a `python -c` command line. + */ +const MODULE_NAME = /^[A-Za-z_]\w*(\.[A-Za-z_]\w*)*$/; + /** * Manages per-course Python environments for `python-notebook` courses. * @@ -146,6 +152,11 @@ export class EnvironmentManager { const results: { module: string; ok: boolean }[] = []; for (const module of modules) { + if (!MODULE_NAME.test(module)) { + log.warn(`Not a valid Python module name, skipping: ${module}`); + results.push({ module, ok: false }); + continue; + } const code = await runPython(api, env, ["-c", `import ${module}`]); results.push({ module, ok: code === 0 }); } @@ -196,7 +207,9 @@ export class EnvironmentManager { return envs[0]; default: log.warn( - `Found multiple virtual environments, using first: ${envs.join(", ")}`, + `Found multiple virtual environments, using first: ${envs + .map((e) => e.name) + .join(", ")}`, ); return envs[0]; }