Skip to content

Commit ffe16b0

Browse files
committed
Rename sandbox dir to .bblocks-sandbox and detect stale venvs
Renames the sandbox directory from .transforms-sandbox to .bblocks-sandbox to reflect that it now hosts both transform and validator plugin venvs. Also adds a shebang-target check to venv_needs_recreate(): the existing version check was insufficient when the sandbox directory was renamed, because pip scripts have an absolute shebang baked in at venv creation time. Moving the venv silently breaks pip even when the Python version matches. The new check reads pip's first line and verifies the target path exists, catching both renamed-sandbox and removed-interpreter cases.
1 parent dff5eb6 commit ffe16b0

1 file changed

Lines changed: 27 additions & 3 deletions

File tree

ogc/bblocks/sandbox.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import re
34
import shutil
45
import sys
56
from pathlib import Path
@@ -8,12 +9,35 @@
89

910
_PYTHON_VERSION = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
1011

11-
SANDBOX_DIR_NAME = '.transforms-sandbox'
12+
SANDBOX_DIR_NAME = '.bblocks-sandbox'
13+
_OLD_SANDBOX_DIR_NAME = '.transforms-sandbox'
14+
15+
16+
def pip_slug(pip_deps: list[str]) -> str:
17+
"""Return a stable, human-readable directory name for a set of pip specifiers.
18+
19+
The slug identifies the venv that would result from installing exactly these
20+
deps. Same deps → same slug → shared venv. Different version → different slug.
21+
"""
22+
key = ','.join(sorted(pip_deps))
23+
slug = re.sub(r'[^a-zA-Z0-9_-]+', '_', key)
24+
slug = re.sub(r'_+', '_', slug).strip('_')
25+
return slug or 'default'
1226

1327

1428
def venv_needs_recreate(venv_dir: Path) -> bool:
15-
"""Return True if the venv is absent or was built with a different Python version."""
16-
if not (venv_dir / 'bin' / 'pip').exists():
29+
"""Return True if the venv is absent, broken, or was built with a different Python version."""
30+
pip_bin = venv_dir / 'bin' / 'pip'
31+
if not pip_bin.exists():
32+
return True
33+
# Verify pip's shebang target still exists (catches renamed sandbox dirs and removed interpreters).
34+
try:
35+
first_line = pip_bin.read_text(errors='replace').split('\n', 1)[0]
36+
if first_line.startswith('#!'):
37+
shebang_target = Path(first_line[2:].strip().split()[0])
38+
if not shebang_target.exists():
39+
return True
40+
except OSError:
1741
return True
1842
cfg = venv_dir / 'pyvenv.cfg'
1943
if not cfg.exists():

0 commit comments

Comments
 (0)