fix(deps): exclude nltk 3.10.1, which breaks venvs living inside the working directory (v1) - #6607
Merged
Merged
Conversation
…working directory (v1) Ports 1a0c3bd from main to v1. Applied by hand rather than cherry-picked, because the extras lists have diverged between the branches; the same three extras reach nltk on v1. nltk 3.10.1 added an import-time security hook (nltk/inisec.py) that breaks any ADK code path reaching nltk, in two independent ways: 1. It installs a meta-path finder that raises ImportError for any module whose file resolves under the current working directory while an nltk frame is on the stack. The standard layout puts the virtualenv inside the project (.venv/), so every site-packages module nltk imports looks like a CWD hijack and a plain `import nltk` dies on `import regex`. 2. It calls os.environ.setdefault("PYTHONSAFEPATH", "1"), which leaks into every subprocess started afterwards. PYTHONSAFEPATH stops CPython from prepending the script/CWD entry to sys.path, and that prepend is what causes the eagerly created `google` namespace package (from google-cloud-aiplatform's legacy *-nspkg.pth) to recompute its __path__ and pick up src/google. Without it, `import google.adk` fails with ModuleNotFoundError in child interpreters. Note this happens even when the nltk import itself fails, because the hook installs before the failure, so catching the ImportError does not undo it. Three extras reach nltk, and all three are constrained here: * eval -> rouge-score -> nltk. * extensions -> llama-index-{embeddings-google-genai,readers-file} -> llama-index-core -> nltk. * test -> both of the above. nltk removed the hook in 3.10.2, released after the original commit landed on main, so a fresh resolve already picks up a good version. 3.10.1 is not yanked, though, so it stays reachable via stale lockfiles, lowest-version resolution and pinned or mirrored indexes. The `!=` form excludes only the bad release and keeps v1 in parity with main.
wuliang229
marked this pull request as ready for review
August 6, 2026 01:03
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Link to Issue or Description of Change
Ports 1a0c3bd from
maintov1. Original PR onmain: #6576. Upstream: nltk/nltk#3730, reverted by nltk/nltk#3732.Applied by hand rather than cherry-picked — the extras lists have diverged between the branches (
mainhasgoogle-cloud-texttospeech,mcp,lxmlin placesv1does not), so the cherry-pick would not apply cleanly. The same three extras reachnltkonv1.Problem:
nltk3.10.1 added an import-time security hook (nltk/inisec.py) that breaks any ADK code path reaching nltk, in two independent ways:ImportErrorfor any module whose file resolves under the CWD while an nltk frame is on the stack. The standard layout puts the virtualenv inside the project (.venv/), so everysite-packagesmodule nltk imports looks like a CWD hijack, and a plainimport nltkdies onimport regex.os.environ.setdefault("PYTHONSAFEPATH", "1"), which leaks into every subprocess started afterwards.PYTHONSAFEPATHstops CPython from prepending the script/CWD entry tosys.path, and that prepend is what causes the eagerly createdgooglenamespace package (fromgoogle-cloud-aiplatform's legacy*-nspkg.pth) to recompute its__path__and pick upsrc/google. Without it,import google.adkfails withModuleNotFoundErrorin child interpreters. This fires even when the nltk import itself fails, because the hook installs before the failure — catching theImportErrordoes not undo it.Solution:
Exclude the single bad release from the three extras that reach nltk:
evalrouge-score->nltkextensionsllama-index-{embeddings-google-genai,readers-file}->llama-index-core->nltktest!=rather than an upper bound, so a fixed release is picked up automatically.Note on current urgency
This is parity and defense-in-depth, not an active CI fix. nltk 3.10.2 shipped the upstream revert on 2026-08-05, after the original commit landed on
main, so a fresh resolve already selects a good version:3.10.1 is not yanked, however, so it stays reachable via stale lockfiles, lowest-version resolution, and pinned or mirrored indexes. Landing this keeps
v1in parity withmainat zero cost — the!=form does not block 3.10.2.Testing Plan
Unit Tests:
No test added — this mirrors the commit as it landed on
main, which ispyproject.toml-only. (The guard test proposed in #6576 was dropped before that commit landed, andtests/unittests/test_release_dependencies.pydoes not exist onv1.)Verification performed:
pyproject-fmtv2.5.0 — the rev pinned in this branch's.pre-commit-config.yaml— reportsno change, so comment alignment is correct.rouge-score>=0.1.2with and without the constraint: both now resolve tonltk==3.10.2, confirming the exclusion does not pin the branch to an old nltk.uv.lockdeliberately untouched, matching themaincommit.