From 6509f609dceb0f1de467920c3c9aa53ad5a529b5 Mon Sep 17 00:00:00 2001 From: ayushcodes10 Date: Wed, 23 Sep 2026 12:16:33 +0530 Subject: [PATCH 1/3] Re exec the hash seed pin as a module, not by replaying argv[0] The previous form replayed sys.argv[0] as the script path to run, which happens to work for a POSIX console script wrapper or a python dash m invocation, both of which are real, runnable Python content. It does not work for a uv, pip, or pipx console script launcher on Windows, which installs as a native executable stub with no such content, so the interpreter has nothing to open and every affected command failed outright the moment it tried to pin the seed. Re execing through the module flag instead never depends on argv[0] being anything runnable at all, so a launcher stub that is not even a real file no longer matters, and this now matches the exact invocation shape the end to end test for this function already exercised and proved working. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh --- graphify/__main__.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/graphify/__main__.py b/graphify/__main__.py index d4f266ce4b..a2c5416de2 100644 --- a/graphify/__main__.py +++ b/graphify/__main__.py @@ -522,7 +522,17 @@ def _pin_hash_seed_if_needed() -> None: if "PYTHONHASHSEED" in os.environ or "PYTEST_CURRENT_TEST" in os.environ: return try: - os.execvpe(sys.executable, [sys.executable, *sys.argv], {**os.environ, "PYTHONHASHSEED": "0"}) + # Re-exec as a module (-m graphify) rather than replaying sys.argv[0] + # as a script path: that works for a POSIX console-script wrapper or + # a `python -m graphify` invocation, but a uv/pip/pipx console-script + # launcher on Windows is a native .exe with no .py content, so + # `python.exe ` fails outright with "can't open + # file" -- every command this function touches (#3779). + os.execvpe( + sys.executable, + [sys.executable, "-m", "graphify", *sys.argv[1:]], + {**os.environ, "PYTHONHASHSEED": "0"}, + ) except OSError: pass From e2fd1c4f306a00b7ff07cb28ffa364c8a7766d82 Mon Sep 17 00:00:00 2001 From: ayushcodes10 Date: Wed, 23 Sep 2026 12:16:41 +0530 Subject: [PATCH 2/3] Update hash seed tests for the module based re exec and add a regression The existing probe assertions now expect the module flag form. A new test drives the probe with a launcher stub path that is not even a real file in place of argv zero, confirming the fix no longer depends on it being anything runnable, the exact shape of the Windows uv launcher regression this closes. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh --- tests/test_pin_hash_seed.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/test_pin_hash_seed.py b/tests/test_pin_hash_seed.py index d20eeb9ac0..2aad777b5b 100644 --- a/tests/test_pin_hash_seed.py +++ b/tests/test_pin_hash_seed.py @@ -56,10 +56,23 @@ def test_reexecs_for_hash_sensitive_commands_when_unset(): for cmd in ("update", "extract", "cluster-only", "label"): outcome = _run_probe(["graphify", cmd, "."]) assert outcome["called"], f"{cmd} must re-exec with PYTHONHASHSEED pinned" - assert outcome["argv"] == [sys.executable, "graphify", cmd, "."] + assert outcome["argv"] == [sys.executable, "-m", "graphify", cmd, "."] assert outcome["env_hashseed"] == "0" +def test_reexec_does_not_depend_on_argv0_being_a_runnable_script(): + """#3779: a uv/pip/pipx console-script launcher on Windows is a native + .exe with no .py content, so `python.exe ` fails + outright with "can't open file" the moment argv[0] is replayed as a + script path. Re-execing via `-m graphify` never touches argv[0] at + all, so a launcher stub that isn't even a real file must not matter.""" + outcome = _run_probe(["/some/launcher/stub/with/no/py/content", "update", "."]) + assert outcome["called"] + assert outcome["argv"] == [sys.executable, "-m", "graphify", "update", "."], ( + "the launcher stub path must never appear in the re-exec argv" + ) + + def test_does_not_reexec_when_already_set(): outcome = _run_probe(["graphify", "update", "."], extra_env={"PYTHONHASHSEED": "1"}) assert not outcome["called"], "an explicit PYTHONHASHSEED must never be overridden" From 01fe6c863d2a994b216e2407d738f52502b05dc4 Mon Sep 17 00:00:00 2001 From: ayushcodes10 Date: Wed, 23 Sep 2026 12:16:59 +0530 Subject: [PATCH 3/3] Extend changelog entry for the hash seed fix with issue 3779 Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b96765d4d8..3e68eef802 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ Full release notes with details on each version: [GitHub Releases](https://githu - Feature: five new language extractors — **COBOL** (`.cbl`/`.cob`/`.cobol`/`.cpy`; programs, paragraphs, `PERFORM`/`CALL`/`COPY`, pure-regex, no new dependency) (#3713, thanks @Abdul535), **VB.NET** (`.vb`; case-insensitive types/methods, `Inherits`/`Implements`/`Handles`) (#3717, thanks @Abdul535), **R** (`.r`/`.R`; assignment-form function defs, `library`/`source`, S4/R6 classes) (#3715, thanks @Abdul535), **Solidity** (`.sol`; contracts/interfaces/libraries, `is` inheritance, imports, modifiers) (#3716, thanks @Abdul535), and **Erlang** (`.erl`/`.hrl`/`.escript`; modules, functions by arity, behaviours, local + remote `foo:bar()` calls) (#3714, thanks @Abdul535). The R and Erlang grammars ship via the `r`/`erlang` extras (they have no standalone PyPI wheel); Solidity and VB.NET have their own extras. - Feature: Go interface method requirements now resolve to the interface, and their parameter/return types emit `references` edges (#3672, #3737, thanks @rajatnagda45, @oleksii-tumanov). - Feature: a Rust `self.method()` call resolves across files for simple generic impls (`impl Foo`) (#3653, thanks @oleksii-tumanov). -- Fix: `graph.json` is now deterministic across runs — `update`/`extract`/`cluster-only`/`label` pin `PYTHONHASHSEED` via a one-time re-exec, so hash-seed-sensitive community detection (Leiden/Louvain) produces identical output run-to-run and matches hook-triggered rebuilds (#3743, #3641, thanks @ayushcodes10). +- Fix: `graph.json` is now deterministic across runs — `update`/`extract`/`cluster-only`/`label` pin `PYTHONHASHSEED` via a one-time re-exec, so hash-seed-sensitive community detection (Leiden/Louvain) produces identical output run-to-run and matches hook-triggered rebuilds. The re-exec now runs as `python -m graphify` instead of replaying `argv[0]` as a script path, since a uv/pip/pipx console-script launcher on Windows is a native `.exe` with no `.py` content — every affected command previously failed outright with "can't open file" there (#3743, #3641, #3779, thanks @ayushcodes10). - Fix: a same-relation edge collision now keeps the higher-confidence edge (EXTRACTED over INFERRED) instead of resolving by arrival order (#3711, thanks @shobhitagnihotri69). - Fix: a spec-conformant method-node duplicate (dropped class segment / leading dot) is now deduplicated onto its canonical AST node, gated on a method-shaped label and a single unambiguous candidate (#3719, #3705, thanks @shobhitagnihotri69). - Fix: intra-module Go `imports_from` edges now repoint onto the imported package's real file nodes instead of dangling at a `go_pkg_` sink; external/stdlib imports stay external (#3748, thanks @carterko23).