Skip to content

Commit 8a84933

Browse files
committed
Fix exit-code-1 on Windows: config path mismatch and stdout encoding
Two root causes: 1. DATA_DIR mismatch: Electron always writes config/credentials to ~/.auto_note/ but Python scripts in dev mode fall back to PROJECT_DIR when not frozen and not installed to ~/.auto_note/scripts/. On a fresh Windows clone the project root has no config.json, so CANVAS_URL is empty and the first API call exits with code 1. Fix: pass AUTONOTE_DATA_DIR env var from Electron so all four pipeline scripts (downloader, extract_caption, semantic_alignment, note_generation) resolve DATA_DIR correctly regardless of where the script file lives. 2. Windows stdout encoding: Python defaults to cp1252 on Windows when stdout is piped, causing UnicodeEncodeError on tqdm/Unicode output. Fix: add PYTHONIOENCODING=utf-8 and PYTHONUTF8=1 to subprocess env in both Electron main.js and gui.py.
1 parent ab49771 commit 8a84933

6 files changed

Lines changed: 31 additions & 7 deletions

File tree

downloader.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,12 @@
4141
# Persistent data dir: ~/.auto_note/ when installed (AppImage or scripts/ copy),
4242
# else the project directory (dev mode).
4343
_AUTO_NOTE_DIR = Path.home() / ".auto_note"
44-
if getattr(sys, "frozen", False) or PROJECT_DIR == _AUTO_NOTE_DIR / "scripts":
44+
# AUTONOTE_DATA_DIR env var lets the Electron app (or any launcher) explicitly
45+
# set the data directory so config/credentials are always found regardless of
46+
# where the script file lives (dev mode vs installed).
47+
if os.environ.get("AUTONOTE_DATA_DIR"):
48+
DATA_DIR = Path(os.environ["AUTONOTE_DATA_DIR"])
49+
elif getattr(sys, "frozen", False) or PROJECT_DIR == _AUTO_NOTE_DIR / "scripts":
4550
DATA_DIR = _AUTO_NOTE_DIR
4651
else:
4752
DATA_DIR = PROJECT_DIR

electron/main.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,13 @@ function runProcess(cmd) {
347347

348348
const outDir = getOutputDir();
349349
fs.mkdirSync(outDir, { recursive: true });
350-
const env = { ...process.env, PYTHONUNBUFFERED: '1' };
350+
const env = {
351+
...process.env,
352+
PYTHONUNBUFFERED: '1',
353+
PYTHONIOENCODING: 'utf-8', // prevent UnicodeEncodeError on Windows cp1252 consoles
354+
PYTHONUTF8: '1', // Python 3.7+ UTF-8 mode (also forces utf-8 on Windows)
355+
AUTONOTE_DATA_DIR: DATA_DIR, // tell scripts where to find config/credentials
356+
};
351357

352358
// Unix: prefer node-pty so tqdm sees a real tty and uses \r refresh
353359
if (process.platform !== 'win32' && nodePty) {
@@ -408,7 +414,7 @@ async function runInstaller(basePython, sendLog, sendDone) {
408414
const runStep = (cmd, args) => new Promise((resolve) => {
409415
const proc = spawn(cmd, args, {
410416
stdio: ['ignore', 'pipe', 'pipe'],
411-
env: { ...process.env, PYTHONUNBUFFERED: '1' },
417+
env: { ...process.env, PYTHONUNBUFFERED: '1', PYTHONIOENCODING: 'utf-8', PYTHONUTF8: '1' },
412418
// On Windows use explicit shell for commands in PATH
413419
...(process.platform === 'win32' ? { shell: false } : {}),
414420
});

extract_caption.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424

2525
PROJECT_DIR = Path(__file__).parent
2626
_AUTO_NOTE_DIR = Path.home() / ".auto_note"
27-
if getattr(sys, "frozen", False) or PROJECT_DIR == _AUTO_NOTE_DIR / "scripts":
27+
if os.environ.get("AUTONOTE_DATA_DIR"):
28+
DATA_DIR = Path(os.environ["AUTONOTE_DATA_DIR"])
29+
elif getattr(sys, "frozen", False) or PROJECT_DIR == _AUTO_NOTE_DIR / "scripts":
2830
DATA_DIR = _AUTO_NOTE_DIR
2931
else:
3032
DATA_DIR = PROJECT_DIR

gui.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,12 @@ def _process_chunk(raw: bytes) -> None:
612612
# \r for in-place refresh. On Windows pty is unavailable so
613613
# fall back to a plain pipe (progress bars produce extra lines
614614
# but work correctly).
615-
env = {**os.environ, "PYTHONUNBUFFERED": "1"}
615+
env = {
616+
**os.environ,
617+
"PYTHONUNBUFFERED": "1",
618+
"PYTHONIOENCODING": "utf-8",
619+
"PYTHONUTF8": "1",
620+
}
616621
_use_pty = False
617622
if sys.platform != "win32":
618623
try:

note_generation.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@
3232
PROJECT_DIR = Path(__file__).parent
3333
import sys as _sys
3434
_AUTO_NOTE_DIR = Path.home() / ".auto_note"
35-
if getattr(_sys, "frozen", False) or PROJECT_DIR == _AUTO_NOTE_DIR / "scripts":
35+
import os as _os
36+
if _os.environ.get("AUTONOTE_DATA_DIR"):
37+
DATA_DIR = Path(_os.environ["AUTONOTE_DATA_DIR"])
38+
elif getattr(_sys, "frozen", False) or PROJECT_DIR == _AUTO_NOTE_DIR / "scripts":
3639
DATA_DIR = _AUTO_NOTE_DIR
3740
else:
3841
DATA_DIR = PROJECT_DIR

semantic_alignment.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@
4141
PROJECT_DIR = Path(__file__).parent
4242
import sys as _sys
4343
_AUTO_NOTE_DIR = Path.home() / ".auto_note"
44-
if getattr(_sys, "frozen", False) or PROJECT_DIR == _AUTO_NOTE_DIR / "scripts":
44+
import os as _os
45+
if _os.environ.get("AUTONOTE_DATA_DIR"):
46+
DATA_DIR = Path(_os.environ["AUTONOTE_DATA_DIR"])
47+
elif getattr(_sys, "frozen", False) or PROJECT_DIR == _AUTO_NOTE_DIR / "scripts":
4548
DATA_DIR = _AUTO_NOTE_DIR
4649
else:
4750
DATA_DIR = PROJECT_DIR

0 commit comments

Comments
 (0)