Skip to content

Development with VS Code

This guide covers the full development workflow in Visual Studio Code. The project ships committed task definitions and settings under .vscode/. Once you select a Python interpreter, every common task is available from the Command Palette with no extra configuration.


Setup

1. Fork, clone, and install

Follow steps 1–4 of the setup walkthrough in the contributing guide to fork the repository, clone it, and install dependencies. Then come back here for VS Code–specific setup.

2. Open in VS Code

code ChuMicro

Or File → Open Folder → select the ChuMicro directory.

VS Code may prompt you to install recommended extensions. Accept, or install manually:

  • Python (ms-python.python): required
  • Pylance (ms-python.vscode-pylance): recommended for type checking

4. Select the Python interpreter

Open the Command Palette (⌘⇧P / Ctrl+Shift+P) → Python: Select Interpreter.

If you already have a .venv: - Select it from the list

If not, create one first:

python scripts/prepare_workspace.py

Then select the .venv interpreter from the Command Palette.

5. Run workspace setup

Open the integrated terminal (⌃\`` / `` Ctrl+ ``) and run:

python scripts/run.py setup

This installs dependencies, runs editable installs for every library and support package, and regenerates IDE configs. It also materializes three gitignored starter files at the repo root if they're missing: devices.yml, workspace.yml, and secrets.toml. If you plan to run functional tests on real hardware, see Device Testing for board registration and secrets.toml setup.

setup produces a lot of output. Look for this at the end:

============================================================
  Workspace is ready
============================================================

Import resolution

The mono-workspace layout means each library has its own src/ directory. VS Code resolves imports through two generated config files:

  • pyrightconfig.json: sets extraPaths for each library's src/ directory
  • .vscode/settings.json: sets python.analysis.extraPaths for Pylance

Both are generated by sync-ide (called automatically during setup). Imports like from chumicro_timing import ticks_ms should resolve without errors.

If imports show as unresolved:

  1. Run python scripts/run.py sync-ide in the terminal
  2. Reload the window: Command Palette → Developer: Reload Window

Note: VS Code uses extraPaths for import resolution. You don't need to run pip install -e manually. The workspace setup script handles editable installs automatically.

Running tasks

The project provides pre-configured tasks in .vscode/tasks.json. Open the Command Palette (⌘⇧P / Ctrl+Shift+P) → Tasks: Run Task:

Task What it runs
Preflight Full CI gate: lint, test, build, docs, examples, compat
Lint Ruff across the workspace
Test CPython tests for all libraries
Test Scripts Infrastructure tests for scripts/
Build Build all package distributions
Verify Examples AST-based import check of all examples
Docs Build documentation for all libraries
Docs Preview Deploy and serve versioned docs locally
Check API Detect API breakages
Check Version Verify VERSION bumps
Test MicroPython Library unit tests on the MicroPython unix port
Test CircuitPython Library unit tests on the CircuitPython unix port
Test All Runtimes Unit tests on CPython + MicroPython + CircuitPython (parallelized)
Setup python scripts/run.py setup: installs dev deps, runs editable installs, regenerates IDE configs, generates starter device configs
Prepare Workspace Lower-level workspace prep: invokes scripts/prepare_workspace.py directly (advanced users; Setup is usually what you want)
Test Functional Run all hardware-gated functional suites: test-libraries-functional then test-workbench-functional against devices.yml defaults
Test Libraries Functional Run defaults-backed real-board functional tests for library code
Test Workbench Functional Run hardware-gated functional tests for every workbench/*/functional_tests/ suite

Output appears in the Terminal panel at the bottom of the window.

Running tests

From the task runner (with coverage)

Command Palette → Tasks: Run TaskTest. This runs all libraries with the coverage threshold and leaves a .coverage data file at the project root. To browse coverage visually, see Browsing coverage below.

From the test explorer (quick check, no coverage)

VS Code's Testing panel (beaker icon in the sidebar, or ⌘⇧T / Ctrl+Shift+T) discovers tests via the python.testing.pytestArgs setting in .vscode/settings.json.

Click the ▶ button next to any test file or function to run it. This is fast for iterating but does not produce coverage data or enforce the coverage threshold.

For real-board functional_tests/, the same Testing panel can target the explicit functional_tests/ file, directory, or function. The repository's pytest device plugin intercepts those targets and routes them to hardware. The test tree shows extra Setup: <runtime> and Run overhead: <runtime> nodes alongside the individual tests.

If no device is configured yet, pytest skips the run with a message telling you to generate or fill in devices.yml. See Device Testing for setup, the schema, and CLI options.

From the terminal

The integrated terminal (⌃` / Ctrl+`) works the same as any terminal:

pytest libraries/timing/tests/

Validating your work

Quick validation (during development)

  1. Click ▶ next to your test in the Testing panel
  2. Green ✓ = passing, red ✗ = failing
  3. Click a failed test to see the assertion error

Full validation (before opening a PR)

Command Palette → Tasks: Run TaskPreflight.

When it passes, the terminal shows:

Preflight passed.  Required CI checks should pass.

When it fails, the terminal shows the failing step. The development loop in the contributing guide covers how to read the common failures (coverage gaps, ruff style violations, griffe docstring warnings, a missed VERSION bump, cross-runtime breaks) and how to reproduce each. Terminal links are clickable: Ctrl+click / ⌘+click a file:line reference to jump straight to it.

Step-by-step validation

If preflight fails, run individual tasks to isolate the problem:

  1. Command Palette → Tasks: Run TaskLint
  2. Command Palette → Tasks: Run TaskTest
  3. Command Palette → Tasks: Run TaskVerify Examples
  4. Command Palette → Tasks: Run TaskDocs

Or use the terminal for more control:

# Test one library with the coverage gate
python scripts/run.py test --libraries timing

# Day-to-day iteration (no coverage gate)
pytest libraries/timing/tests/ -k heartbeat -x -v

Device functional tests from the terminal or task runner

The committed VS Code workspace also includes a Test Libraries Functional task, which runs:

python scripts/run.py test-libraries-functional

That command uses the defaults: section in devices.yml to choose the target runtime(s), board(s), and default deploy mode.

Common overrides:

python scripts/run.py test-libraries-functional --library timing
python scripts/run.py test-libraries-functional --runtime both
python scripts/run.py test-libraries-functional --circuitpython-device desk-cp-board
python scripts/run.py test-libraries-functional --library timing --deploy-mode flash

Useful shortcuts

Action macOS Windows/Linux
Open Command Palette ⌘⇧P Ctrl+Shift+P
Open terminal ⌃` Ctrl+`
Run task ⌘⇧P → "Tasks: Run Task" Ctrl+Shift+P → "Tasks: Run Task"
Go to file ⌘P Ctrl+P
Go to symbol ⌘⇧O Ctrl+Shift+O
Find in files ⌘⇧F Ctrl+Shift+F
Toggle test explorer ⌘⇧T Ctrl+Shift+T

Browsing coverage

Running the Test task (or python scripts/run.py test from the terminal) produces a .coverage data file at the project root. To see it in the editor gutter, install the Coverage Gutters extension, generate an XML report with python -m coverage xml, and toggle the display with the Coverage Gutters: Display Coverage command. Coverage Gutters reads coverage.xml and highlights covered and uncovered lines directly in the editor. (coverage.xml is gitignored.)

For the HTML report and the rest of the coverage workflow, see Browsing coverage in the Style Guide.

Quirks and tips

  • Pylance may show false-positive errors for micropython imports (e.g., from micropython import const). These modules only exist on-device. The code handles this with try/except at the module level.
  • Test discovery in the sidebar may be slow on first open. Wait for Pylance to finish indexing (check the status bar).
  • If a new library is added, run python scripts/run.py sync-ide to regenerate pyrightconfig.json and .vscode/settings.json. Reload the window afterward.
  • .vscode/tasks.json and .vscode/settings.json are committed and shared. Workspace-specific settings (.vscode/launch.json, etc.) are gitignored if not present.
  • Terminal links are clickable. When a lint error or test failure shows file.py:42, Ctrl+click / ⌘+click to jump directly to that line.
  • Device-testing support is wired through ordinary pytest. The committed VS Code settings and tasks are generated from sync-ide, and explicit functional_tests/ targets go through the same plugin path PyCharm uses. A dedicated live VS Code validation pass remains on the project plan, so VS Code-specific bugs are worth reporting.