# Auto-activate the Python venv in VS Code terminals ## Context Opening a terminal in VS Code does not activate the project's Python venv. Two causes: 1. **The venv is not where VS Code looks.** It lives at `backend/venv`, but the Python extension's auto-discovery only scans for `.venv`/`venv` directly under the opened workspace folder (`C:\dev_projects\ScalesApp`) — one level above it. 2. **No interpreter is configured.** There is no `.vscode/settings.json` in the project, and the user-level settings contain no `python.defaultInterpreterPath`. Without a known interpreter, the extension has nothing to activate. Separately, none of the `run_*.bat` scripts activate the venv — they call `python` / `uvicorn` bare, so they only work when a venv happens to already be active. **Outcome:** a single `.venv` at the project root that VS Code discovers automatically, plus batch scripts that activate it themselves and work from any shell state. ### Findings that shape the plan - The existing `backend/venv` (Python 3.11.9, 138 MB) already has the dependencies from **all three** requirements files installed (Django + uvicorn, Flask + pyserial + pystray + PyInstaller). One shared root venv is therefore a faithful consolidation, not a new decision. - Base interpreter `C:\dev\Python\Python311\python.exe` (3.11.9) is present — verified. - `.gitignore` **already** ignores `.vscode/` and `venv/`, and has a `.venv` entry. The user chose to keep VS Code settings local, so **no `.gitignore` change is needed**. ### Decisions made - Consolidate into one root `.venv` (standard layout, zero-config discovery). - Version conflicts between requirements files: **highest version wins** — install order chosen so the result is `python-dotenv==1.0.1` and `requests==2.32.5`. - Delete `backend/venv` only **after** the new venv is verified working. --- ## Steps ### 1. Create the root venv ```bat C:\dev\Python\Python311\python.exe -m venv C:\dev_projects\ScalesApp\.venv ``` → **verify:** `.venv\Scripts\python.exe --version` prints `Python 3.11.9`. ### 2. Install dependencies (order matters) Install so that the higher pin of each conflicting package is applied last: ```bat .venv\Scripts\python.exe -m pip install --upgrade pip .venv\Scripts\python.exe -m pip install -r backend\requirements.txt .venv\Scripts\python.exe -m pip install -r test_comport_writer\requirements.txt .venv\Scripts\python.exe -m pip install -r serial_bridge\requirements.txt ``` `serial_bridge` pins `requests==2.32.5` (higher) and `python-dotenv==1.0.0` (lower), so a final explicit pin is required to land on the intended "highest wins" result: ```bat .venv\Scripts\python.exe -m pip install "python-dotenv==1.0.1" ``` → **verify:** `pip freeze` shows `python-dotenv==1.0.1` and `requests==2.32.5`, and `pip check` reports no broken dependencies. ### 3. Create `.vscode/settings.json` (local only, already gitignored) New file — `.vscode/settings.json`: ```json { "python.defaultInterpreterPath": "${workspaceFolder}\\.venv\\Scripts\\python.exe", "python.terminal.activateEnvironment": true } ``` `python.terminal.activateEnvironment` defaults to `true`, but is stated explicitly here so the intent is visible and survives a future user-settings change. → **verify:** reload the VS Code window, open a fresh terminal, and confirm the prompt is prefixed with `(.venv)`. ### 4. Make the batch scripts self-contained Add a `call` to the venv activation script so each one works regardless of shell state. - **`run_server.bat`** — currently `cd .\backend\` then `uvicorn ...` (also note: the file has no trailing newline). Activate from the root *before* the `cd`: ```bat @echo off call "%~dp0.venv\Scripts\activate.bat" cd /d "%~dp0backend" uvicorn scalesapp.asgi:application --host 127.0.0.1 --port 8000 --reload ``` - **`run_comport_reader.bat`** — currently `python .\serial_bridge\app.py`: ```bat @echo off call "%~dp0.venv\Scripts\activate.bat" python "%~dp0serial_bridge\app.py" ``` - **`run_test.bat`** — currently `python .\test_comport_writer\test_writer.py`: ```bat @echo off call "%~dp0.venv\Scripts\activate.bat" python "%~dp0test_comport_writer\test_writer.py" ``` `%~dp0` (the directory of the batch file itself, with trailing backslash) makes each script independent of the caller's working directory. `stop.bat` needs no change — it only calls `taskkill`. ### 5. Remove the old venv — only after step 6 passes ```bat rmdir /s /q C:\dev_projects\ScalesApp\backend\venv ``` Reclaims 138 MB and prevents two interpreters drifting apart. --- ## Verification Run in order; do not proceed to the deletion in step 5 until all of these pass. 1. **Interpreter** — `.venv\Scripts\python.exe --version` → `Python 3.11.9`. 2. **Dependencies** — `.venv\Scripts\python.exe -m pip check` → no issues; `pip freeze` shows `python-dotenv==1.0.1`, `requests==2.32.5`. 3. **Auto-activation** — reload the VS Code window, open a **new** terminal: prompt shows `(.venv)`; `where python` resolves to `...\ScalesApp\.venv\Scripts\python.exe`. 4. **Django backend** — `run_server.bat` from a plain `cmd.exe` (no venv pre-activated): uvicorn starts and serves on `http://127.0.0.1:8000`. Also confirm `python manage.py check` in `backend/` reports no issues. 5. **Serial bridge** — `run_comport_reader.bat` starts the Flask server on port 5000 without an import error (`pyserial`, `flask`, `pystray` all resolve). 6. **Test writer** — `run_test.bat` launches without an import error. If step 4 or 5 fails on a missing package, the old `backend/venv` is still intact — install the missing package into `.venv` rather than rolling back. --- ## Files touched | File | Change | |---|---| | `.venv/` | **new** — root venv (gitignored) | | `.vscode/settings.json` | **new** — interpreter path (gitignored, local only) | | `run_server.bat` | activate venv; use `%~dp0` for path independence | | `run_comport_reader.bat` | same | | `run_test.bat` | same | | `backend/venv/` | **deleted** after verification | No application code changes. `.gitignore` needs no edit — `.vscode/`, `venv/` and `.venv` are all already covered.