fe9fb71860
Plans record the decisions behind each feature and, for the protocol and licensing work, what remains unvalidated against real hardware. ~WRL0003.tmp was a Word autosave artifact committed by accident. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
165 lines
6.1 KiB
Markdown
165 lines
6.1 KiB
Markdown
# 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.
|