fix(compliance): use PYTHON_BIN env var for venv support

Modern Debian/Ubuntu enforces PEP 668 which blocks system-wide pip
installs. The backend now reads PYTHON_BIN from the environment
(defaulting to 'python3') so each server can point to a venv.
Updates README with venv setup instructions.
This commit is contained in:
2026-04-01 12:47:50 -06:00
parent d0087ba9b7
commit 8aef51b59a
2 changed files with 21 additions and 4 deletions

View File

@@ -68,7 +68,7 @@ The application provides:
- Node.js 18 or later - Node.js 18 or later
- npm - npm
- Python 3 with `pandas` and `openpyxl` (required for compliance xlsx parsing) - Python 3 with a venv containing `pandas` and `openpyxl` (required for compliance xlsx parsing)
--- ---
@@ -97,13 +97,29 @@ npm install
### 4. Install Python dependencies ### 4. Install Python dependencies
Modern Debian/Ubuntu systems enforce PEP 668 and block system-wide pip installs. Create a virtual environment instead:
```bash ```bash
cd backend/scripts # Install venv support if needed
pip install -r requirements.txt apt install -y python3-venv python3-full
# Create the venv (once per server, from the app root)
python3 -m venv /home/cve-dashboard/venv
# Install packages into the venv
/home/cve-dashboard/venv/bin/pip install -r backend/scripts/requirements.txt
``` ```
Required packages: `pandas>=2.0.0`, `openpyxl>=3.0.0` Required packages: `pandas>=2.0.0`, `openpyxl>=3.0.0`
Then set the `PYTHON_BIN` environment variable so the backend uses the venv Python:
```bash
export PYTHON_BIN=/home/cve-dashboard/venv/bin/python3
```
Add this to the server's startup environment (e.g., your systemd unit or `.env` file) so it persists across restarts. If `PYTHON_BIN` is not set, the backend falls back to the system `python3`.
> The bulk notes import script (`import_notes_from_csv.py`) uses only Python stdlib and does **not** require these packages. > The bulk notes import script (`import_notes_from_csv.py`) uses only Python stdlib and does **not** require these packages.
### 5. Initialize the database ### 5. Initialize the database

View File

@@ -17,6 +17,7 @@ const fs = require('fs');
const { spawn } = require('child_process'); const { spawn } = require('child_process');
const PARSER_SCRIPT = path.join(__dirname, '../scripts/parse_compliance_xlsx.py'); const PARSER_SCRIPT = path.join(__dirname, '../scripts/parse_compliance_xlsx.py');
const PYTHON_BIN = process.env.PYTHON_BIN || 'python3';
const TEMP_DIR = path.join(process.cwd(), 'uploads', 'temp'); const TEMP_DIR = path.join(process.cwd(), 'uploads', 'temp');
const ALLOWED_TEAMS = new Set(['STEAM', 'ACCESS-ENG', 'ACCESS-OPS', 'INTELDEV']); const ALLOWED_TEAMS = new Set(['STEAM', 'ACCESS-ENG', 'ACCESS-OPS', 'INTELDEV']);
@@ -47,7 +48,7 @@ function dbAll(db, sql, params = []) {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function parseXlsx(filePath) { function parseXlsx(filePath) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const py = spawn('python3', [PARSER_SCRIPT, filePath]); const py = spawn(PYTHON_BIN, [PARSER_SCRIPT, filePath]);
let out = ''; let out = '';
let err = ''; let err = '';
py.stdout.on('data', d => { out += d; }); py.stdout.on('data', d => { out += d; });