Skip to content

Commit 8c3ec2c

Browse files
JonZeollaclaude
andcommitted
fix: extract VERSION via file parsing instead of Python import
Replace the namespace-package import (`from src.X import __version__`) with a helper script that reads __init__.py directly. The script resolves the file path relative to its own location, avoiding CWD and import-mechanism issues on Windows. Includes ZENABLE_LOGLEVEL=DEBUG support for diagnostics. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 85fc50d commit 8c3ec2c

3 files changed

Lines changed: 57 additions & 1 deletion

File tree

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ jobs:
105105
windows-smoke-test:
106106
name: Windows Smoke Test
107107
runs-on: windows-latest
108+
env:
109+
ZENABLE_LOGLEVEL: DEBUG
108110
steps:
109111
# Note: no checkout step. The cookiecutter template directory contains
110112
# characters (pipe, quotes) that are illegal on NTFS, so we cannot check

{{cookiecutter.project_name|replace(" ", "")}}/Taskfile.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ vars:
1414
PYTHON_VERSION: {{ cookiecutter.python_version }}
1515
SUPPORTED_PLATFORMS: 'linux/amd64,linux/arm64'
1616
VERSION:
17-
sh: uv run python -c "import sys; sys.path.insert(0, 'src'); from {{ '{{.PROJECT_SLUG}}' }} import __version__; print(__version__)"
17+
sh: "{{ '{{.RUN_SCRIPT}}' }} {{ '{{.SCRIPTS_DIR}}' }}/get_version.py {{ '{{.PROJECT_SLUG}}' }}"
1818
RUN_SCRIPT: 'uv run --frozen'
1919
SCRIPTS_DIR: 'scripts'
2020
LOCAL_PLATFORM:
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env python3
2+
"""Extract __version__ from the project's __init__.py without importing it.
3+
4+
This avoids import-mechanism issues (namespace packages, venv state, etc.)
5+
that can occur cross-platform. The script locates the file relative to its
6+
own position in the repo so it works regardless of the caller's CWD.
7+
"""
8+
9+
import os
10+
import pathlib
11+
import re
12+
import sys
13+
14+
FALLBACK = "0.0.0"
15+
16+
17+
def _debug(msg: str) -> None:
18+
if os.environ.get("ZENABLE_LOGLEVEL", "").upper() == "DEBUG":
19+
print(f"get_version: {msg}", file=sys.stderr)
20+
21+
22+
def main() -> None:
23+
if len(sys.argv) < 2:
24+
print(FALLBACK)
25+
sys.exit(0)
26+
27+
project_slug = sys.argv[1]
28+
29+
# Resolve relative to this script's location (scripts/ -> project root)
30+
script_dir = pathlib.Path(__file__).resolve().parent
31+
project_root = script_dir.parent
32+
init_file = project_root / "src" / project_slug / "__init__.py"
33+
34+
_debug(f"cwd={os.getcwd()}")
35+
_debug(f"script_dir={script_dir}")
36+
_debug(f"project_root={project_root}")
37+
_debug(f"init_file={init_file} exists={init_file.exists()}")
38+
39+
if not init_file.exists():
40+
_debug(f"init file not found, falling back to {FALLBACK}")
41+
print(FALLBACK)
42+
sys.exit(0)
43+
44+
text = init_file.read_text(encoding="utf-8")
45+
match = re.search(r'__version__\s*=\s*"(.+?)"', text)
46+
if match:
47+
print(match.group(1))
48+
else:
49+
_debug(f"no __version__ found in {init_file}, falling back to {FALLBACK}")
50+
print(FALLBACK)
51+
52+
53+
if __name__ == "__main__":
54+
main()

0 commit comments

Comments
 (0)