Skip to content

Add multi-course support and Python notebook courses to QDK Learning#3394

Draft
minestarks wants to merge 1 commit into
mainfrom
minestarks/python-learning-2
Draft

Add multi-course support and Python notebook courses to QDK Learning#3394
minestarks wants to merge 1 commit into
mainfrom
minestarks/python-learning-2

Conversation

@minestarks

Copy link
Copy Markdown
Member

This change generalizes the QDK Learning feature to support multiple courses of different kinds, including author-provided Python Jupyter notebook courses, while keeping the Quantum Katas as the default.

"The function just needs to return a value equal to the integer 42.",
"The simplest answer is to return the literal `42` itself."
],
"solution": "@exercise\ndef forty_two():\n return qsharp.eval(\"40 + 2\")",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the katas, we sometimes found that we wanted to provide multiple solutions. If this is a generalization, we might want that here?

"from qdk.widgets import Circuit\n",
"\n",
"# Define a few operations we'll use throughout this unit.\n",
"OPERATIONS = \"\"\"\n",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar enough with python to suggest an alternative, but this seems like a painful level of escaping.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I don't actually know how this got here. Maybe you never actually touch this file and the escaping is done for you when it's persisted?

"id": "circuit-diagrams",
"title": "Generating Circuit Diagrams",
"shortDescription": "Build and visualize quantum circuits with the QDK in Python notebooks.",
"readme": "README.md",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why reference the readme but not the project? They seem similar to me, but I may be missing something.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably don't need to reference either - they have well-known names.

> Quantum Katas (_kaˑta_ | kah-tuh — Japanese for "form", a pattern of learning and practicing new skills) are self-paced, AI-assisted tutorials for quantum computing and Q# programming. Each tutorial includes relevant theory and interactive hands-on exercises designed to test knowledge.

The tools refer to each kata as a "unit." Each unit contains ordered activities (lessons, examples, exercises).
The tools refer to each unit of a course as a "unit." Each unit contains ordered activities (lessons, examples, exercises).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change makes it a little tautological.

**Handling guidance:**

- When the user asks to change courses, call `list-courses` first if you're unsure of the exact `courseId`, match the user's request to a course, then call `switch-course`. After switching, call `show` to surface the new course's current activity and briefly tell the user where they landed.
- Drop-in courses run author-provided code and only load in a **trusted** workspace. If a drop-in course doesn't appear or won't run, the workspace may be in Restricted Mode — suggest trusting the workspace.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little nervous about "suggest trusting the workspace". Maybe "explain that the user will need to trust the workspace to continue and should only do so if they trust the course material provider"?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is moot - our extension is entirely disabled in untrusted workspaces


// Prefer `uv` when it's available — it's faster and is the modern
// default tooling. Fall back to the standard library `venv` module.
if (await this.uvAvailable()) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be covered below, but I'm wondering if we want a way for users to force venv, rather than uv, even if the latter is available.

"This Python installation can't create virtual environments " +
"(the `venv`/`ensurepip` modules are missing). On Debian/Ubuntu " +
"install them with `sudo apt install python3-venv` (matching your " +
"Python version, e.g. `python3.12-venv`), then try again.",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we know their python version?

* are typed here.
*/
private async pythonEnvironmentsApi(): Promise<
| {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: why not name this type?

export const KATAS_COURSE_ID = "katas";

/** Per-course virtual environment folder (under the course working copy). */
export const LEARNING_VENV_DIR = ".venv";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would there be any value in making this name more unique?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like it's in a folder people won't be editing and it might break notebook discovery, so probably not?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside: the default discovery system only looks in the root and one level down - it doesn't recursively search for .venv. There may be a workspace setting to override it

}

/** Read and JSON-parse a course manifest, or `undefined` if absent/invalid. */
private async readManifest(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remind me what guardrails we need when reading untrusted (?) files from disk. Or maybe this only works if they're in a trusted folder?

import * as vscode from "vscode";
import type { LearningService } from "./service.js";

/**

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way to check whether a cell is an exercise is to refer to the exercies.json metadata

@amcasey amcasey left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old kata notebooks at github.com/microsoft/quantumkatas may be useful references

}
],
"environment": {
"importChecks": ["qdk", "qdk.widgets"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we discover these from the cells?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per our offline discussion, that's probably overkill

"id": "circuit-diagrams",
"title": "Generating Circuit Diagrams",
"shortDescription": "Build and visualize quantum circuits with the QDK in Python notebooks.",
"readme": "README.md",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably don't need to reference either - they have well-known names.

@@ -0,0 +1,10 @@
[project]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This (using a standard python project format) is part of achieving our goal that you could get the basic course experience in any jupyter environment.

"exercises": [
{
"id": "forty_two",
"cellIndex": 7,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems brittle. Is the cell ID more stable?

won't start, or the first cell reports a problem, set up and check your
environment here first:

👉 [Check my environment](command:qsharp-vscode.learningDoctor)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be on screen somewhere, in case the notebook doesn't work. This file is basically an excuse to do that - we could find a different place for it.

**Handling guidance:**

- When the user asks to change courses, call `list-courses` first if you're unsure of the exact `courseId`, match the user's request to a course, then call `switch-course`. After switching, call `show` to surface the new course's current activity and briefly tell the user where they landed.
- Drop-in courses run author-provided code and only load in a **trusted** workspace. If a drop-in course doesn't appear or won't run, the workspace may be in Restricted Mode — suggest trusting the workspace.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is moot - our extension is entirely disabled in untrusted workspaces

}
],
"view/item/context": [
{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This hasn't been reviewed by humans.

export const KATAS_COURSE_ID = "katas";

/** Per-course virtual environment folder (under the course working copy). */
export const LEARNING_VENV_DIR = ".venv";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside: the default discovery system only looks in the root and one level down - it doesn't recursively search for .venv. There may be a workspace setting to override it

@@ -0,0 +1,98 @@
// Copyright (c) Microsoft Corporation.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be mergeable with catalog.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants