[Typing] Add Python type annotations across codebase (Part 1: Mechanical) - #5424
[Typing] Add Python type annotations across codebase (Part 1: Mechanical)#5424letitz wants to merge 17 commits into
Conversation
letitz
left a comment
There was a problem hiding this comment.
A quick review of the first few files shows that there are several changes here that modify runtime behavior and should not be in part 1 but rather in part 2.
| predator_result: Optional[dict[str, Any]]) -> Optional[dict[str, Any]]: | ||
| """Parse raw suspected_cls into dict.""" | ||
| if not predator_result: | ||
| if not predator_result or 'result' not in predator_result: |
There was a problem hiding this comment.
This is not a mechanical change, it should go into part 2.
There was a problem hiding this comment.
Reverted to mechanical form with predator_result = cast(dict[str, Any], predator_result['result']). The defensive check is kept in Part 2.
| # with the response. | ||
| predator_result = predator_result['result'] | ||
| result = predator_result['result'] | ||
| if not isinstance(result, dict): |
There was a problem hiding this comment.
Reverted in Part 1 and deferred to Part 2.
| filtered_crash_lines = [] | ||
| linkifier = source_mapper.StackFrameLinkifier(revisions_dict) | ||
| filtered_crash_lines: list[str] = [] | ||
| linkifier = source_mapper.StackFrameLinkifier(revisions_dict or {}) |
There was a problem hiding this comment.
Again, this is not a mechanical change.
There was a problem hiding this comment.
Reverted to linkifier = source_mapper.StackFrameLinkifier(revisions_dict) # type: ignore in Part 1. The revisions_dict or {} fallback is deferred to Part 2.
| self.important) | ||
|
|
||
| def __eq__(self, other): | ||
| def __eq__(self, other: object) -> bool: |
There was a problem hiding this comment.
other should have type Line.
There was a problem hiding this comment.
Updated other parameter to type 'Line'.
|
|
||
| frames = get_stack_frames(crash_state_lines) | ||
| escaped_frames = [markupsafe.escape(f) for f in frames] | ||
| escaped_frames = [str(markupsafe.escape(f)) for f in frames] |
There was a problem hiding this comment.
This is also a runtime change.
There was a problem hiding this comment.
Reverted str(...) wrapper to [markupsafe.escape(f) for f in frames].
4d23846 to
33ca4c4
Compare
|
|
||
| testcase = data_handler.get_testcase_by_id(testcase_id) | ||
| fuzz_target = testcase.get_fuzz_target() | ||
| fuzz_target = cast(data_types.FuzzTarget, testcase.get_fuzz_target()) |
There was a problem hiding this comment.
Do we still need this cast now that ndb models have better types?
There was a problem hiding this comment.
Removed the cast; using fuzz_target = testcase.get_fuzz_target() with assert fuzz_target is not None.
There was a problem hiding this comment.
Adding an assert changes runtime behavior, we should not do that.
623457d to
6571867
Compare
This commit completes the migration of ClusterFuzz's Python dependency management system from Pipenv to uv. pipx is used to install uv locally. Architecture & Configs: - Created root pyproject.toml with 5 dependency groups, centralizing dependency definitions in a single file (from two Pipfiles) and removing the need for the hack where appengine packages were modelled as dev dependencies in src/Pipfile. - Added setuptools==80.9.0 to project dependencies for pkg_resources API support. - Pinned isort~=5.13.2 and pylint~=2.17.7 in dev dependencies to support line length options. - Shared pinned Google client dependencies in vendor-appengine to avoid version mismatches with vendor-core. - Deleted legacy Pipfile* and requirements.txt files. Butler & Runtime Improvements: - Updated _install_third_party in src/local/butler/common.py to use uv and avoid materializing requirements.txt into the repo, which are duplicative of `uv.lock` contents anyway. - Updated src/local/butler/py_unittest.py to preserve src/third_party in sys.path while adding src/appengine/third_party, ensuring both App Engine and core libraries are importable during App Engine unit tests. This fixes an issue where the previous setup assumed third-party packages were not only vendored into third_party directories, but also installed into the virtual environment. - Updated virtual environment guards in src/local/butler/guard.py and CASP CLI wrapper in cli/casp/src/casp/utils/container.py. Scripts, CI, Docker & Docs: - Updated setup scripts in local/ to install pipx and uv and activate .venv. - Updated CI workflows to do the same. - Updated Docker build scripts and Dockerfiles similarly. - Updated bot setup scripts (configs/test/bot/setup/*.bash, windows-init.ps1). - Updated developer and agent documentation. - Updated local/tests/install_deps_test_linux.bash to verify fresh checkout environment setup with uv (.venv, third_party vendoring, bower components, and uv run butler.py lint / py_unittest).
TAG=agy CONV=e3e8364e-3aff-4a79-9c78-17378c583b06
- pyproject.toml: Removed duplicate root dependencies already in vendor-core (cryptography, future, google-cloud-ndb, protobuf, psutil, crcmod); added conditional pywinauto dependency for win32 under dev group. - windows-init.ps1: Reverted redundant PATH modification (pipx ensurepath handles PATH); updated uv sync to use --frozen. - Dockerfiles: Removed redundant --upgrade and --no-deps flags from uv pip install -e /data. - local/install_deps_linux.bash: Made optional gcloud apt packages conditional on rodete and added b/414408644 and b/484368884 references. - local/install_deps_macos.bash: Removed redundant pipx check (handled by Brewfile); added --frozen to uv sync. - local/install_python_deps_linux.bash: Removed extra source .venv/bin/activate call after nodeenv. - src/local/butler/py_unittest.py: Removed unnecessary site.addsitedir call. - CI/Bot setup scripts: Added --frozen flag to all automated uv sync invocations. TAG=agy CONV=e3e8364e-3aff-4a79-9c78-17378c583b06
- pyproject.toml: Moved setuptools==80.9.0 to [dependency-groups] dev. - local/tests/ci_tests.bash & setup scripts: Reverted --frozen flag from uv sync. - local/install_deps_linux.bash: Removed || true from apt-get install on rodete. - Dockerfile: Added explanatory comment for uv and python3.11 symlinks. TAG=agy CONV=e3e8364e-3aff-4a79-9c78-17378c583b06
- pyproject.toml: Moved vendor-core, vendor-appengine, and vendor-platform-specific to [project.optional-dependencies] extras: core, appengine, platform-specific. Added comment explaining special handling for platform-specific binary wheel downloads via pip download in common.py _install_platform_pip. - src/local/butler/common.py: Updated _install_third_party and _install_platform_pip to use uv export --extra. TAG=agy CONV=e3e8364e-3aff-4a79-9c78-17378c583b06
- local/README.md, AGENTS.md, kubernetes_e2e_test.bash, devcontainer.json: Removed redundant explicit pipx/uv installation steps as local/install_deps.bash handles uv setup. - pyproject.toml: Removed redundant packages from appengine optional dependencies group that are already included in core. Updated comment on platform-specific extras to clarify vendoring behavior. - uv.lock: Updated lockfile. TAG=agy CONV=1906a716-4a06-47e6-b2fb-fc2038c78ef6
…ests.bash TAG=agy CONV=1906a716-4a06-47e6-b2fb-fc2038c78ef6
- Configured [[tool.uv.index]] with PyPI (https://pypi.org/simple) as the default index in pyproject.toml. - Regenerated uv.lock so all package sources and wheel URLs point to PyPI/files.pythonhosted.org rather than Google internal pkg.dev. TAG=agy CONV=1906a716-4a06-47e6-b2fb-fc2038c78ef6
The pre-built ci docker image does not have uv installed. Install pipx and use it to install uv before executing the CI test pipeline. TAG=agy CONV=1906a716-4a06-47e6-b2fb-fc2038c78ef6
Avoid Cloud Build substitution parsing errors on shell environment variables by extracting the CI setup and test invocation into a dedicated script. TAG=agy CONV=1906a716-4a06-47e6-b2fb-fc2038c78ef6
Parameterize local/tests/ci_tests_inner.bash to accept the test runner command (defaulting to local/tests/run_tests) and reuse it in cloudbuild.yaml. TAG=agy CONV=1906a716-4a06-47e6-b2fb-fc2038c78ef6
TAG=agy CONV=1906a716-4a06-47e6-b2fb-fc2038c78ef6
TAG=agy CONV=1906a716-4a06-47e6-b2fb-fc2038c78ef6
6571867 to
402421e
Compare
402421e to
59457d7
Compare
This commit introduces Python type annotations across the codebase with zero runtime behavioral impact. TAG=agy CONV=1906a716-4a06-47e6-b2fb-fc2038c78ef6
59457d7 to
21e6419
Compare
Overview
This is Part 1 of the static typing rollout for ClusterFuzz. It introduces comprehensive Python type annotations across all files in
src/appengineandsrc/clusterfuzzwith zero runtime behavioral changes.Part 2 (stacked on top of this PR) contains targeted runtime fixes and defensive checks identified during the typing process.
Summary of Changes
src/appengine,src/clusterfuzz, andsrc/local.google-cloud-ndbintypings/google/cloud/ndb/, including:Model,Expando,Key, andQueryinterfaces.repeated=Trueoverloads across property descriptors (StringProperty,IntegerProperty,LocalStructuredProperty, etc.) ensuring repeated properties resolve directly tolist[T].__get__overloads supporting instance vs class-level attribute access and Datastore comparison operators (<=,>=,==,.IN()).pyproject.tomlandpyrightconfig.jsoncovering all codebase modules.cast(Any, ...)calls on NDB queries and model entities that predated custom stubs.Verification & Safety
uv run ty check: 0 errors (100% clean across all modules)uv run butler.py lint --type-check: 0 errors, 0 warningspython butler.py py_unittest -t core -m: 2,221 tests passed (0 errors, 0 failures)python butler.py py_unittest -t appengine -m: 742 tests passed (0 errors, 0 failures)