Skip to content

chore(typecheck): include top-level tools#612

Open
binaryaaron wants to merge 1 commit into
mainfrom
binaryaaron/pr596-05-typecheck-tools
Open

chore(typecheck): include top-level tools#612
binaryaaron wants to merge 1 commit into
mainfrom
binaryaaron/pr596-05-typecheck-tools

Conversation

@binaryaaron

@binaryaaron binaryaaron commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Removes the top-level tools exclusion from ty checks.
  • Adds typed TOML and proxy helper boundaries for checked tools.

Test plan

  • mise run typecheck
  • mise run format-check

Related issue: #614

Summary by CodeRabbit

  • Bug Fixes

    • Improved lockfile source handling for registry, Git, path, and unrecognized package sources.
    • Improved dependency update handling across project, optional, grouped, and constrained dependencies.
    • Added clearer handling for missing or invalid dependency configuration sections.
  • Maintenance

    • Expanded type checking coverage for tooling scripts.
    • Strengthened internal validation and lifecycle typing for dependency and proxy utilities.

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Changes

Tooling typing and data handling

Layer / File(s) Summary
Enable tool typechecking
pyproject.toml
Removes the tools Python-file exclusion from ty configuration.
Normalize lockfile sources
tools/diff-lockfile.py
Uses structural matching to extract and normalize registry, Git, and path package sources.
Type network guard lifecycle
tools/hf_network_guard_proxy.py
Updates context-manager annotations and adds override/type dependency declarations.
Refactor Dependabot TOML processing
tools/patch_dependabot.py
Adds typed TOML accessors and pattern matching for dependency, constraint, advisory, and pagination handling.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested labels: chore

Suggested reviewers: mckornfield

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: including top-level tools in type checking.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch binaryaaron/pr596-05-typecheck-tools

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added area:dev-ex Affects build or dev experience area:build-dist labels Jun 24, 2026
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-04-checked-typing-coverage branch from c7fbb20 to eceb66e Compare June 24, 2026 18:11
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-05-typecheck-tools branch from 75ff152 to 1e74819 Compare June 24, 2026 18:11
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-04-checked-typing-coverage branch from eceb66e to 46af38a Compare June 24, 2026 18:18
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-05-typecheck-tools branch from 1e74819 to 670ffdd Compare June 24, 2026 18:18
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-04-checked-typing-coverage branch from 46af38a to 0c08cb9 Compare June 24, 2026 18:23
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-05-typecheck-tools branch 3 times, most recently from 9c96037 to 8d55e69 Compare June 24, 2026 21:46
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-04-checked-typing-coverage branch from 62ba809 to 8d3f148 Compare June 24, 2026 21:46
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-05-typecheck-tools branch from 8d55e69 to 97c3d20 Compare June 24, 2026 22:16
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-04-checked-typing-coverage branch 2 times, most recently from 9af5f17 to cf5ea01 Compare June 26, 2026 21:02
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-05-typecheck-tools branch from 97c3d20 to b0fc400 Compare June 26, 2026 21:04
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-04-checked-typing-coverage branch from cf5ea01 to 3f2bc65 Compare June 30, 2026 21:40
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-05-typecheck-tools branch from b0fc400 to 3ca326f Compare June 30, 2026 21:40
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-04-checked-typing-coverage branch from 3f2bc65 to 967deb4 Compare July 6, 2026 18:07
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-05-typecheck-tools branch from 3ca326f to ab75d47 Compare July 6, 2026 18:07
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-04-checked-typing-coverage branch from 967deb4 to a9286fc Compare July 6, 2026 19:23
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-05-typecheck-tools branch 2 times, most recently from ae3cfb7 to f99a9d9 Compare July 8, 2026 16:05
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-04-checked-typing-coverage branch from 0e72757 to 3d5719d Compare July 9, 2026 17:44
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-05-typecheck-tools branch from f99a9d9 to 148fa85 Compare July 9, 2026 17:44
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-04-checked-typing-coverage branch 2 times, most recently from 756d95c to 3d5719d Compare July 10, 2026 21:25
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-04-checked-typing-coverage branch from 3d5719d to 31ff9f5 Compare July 10, 2026 21:29
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-05-typecheck-tools branch 2 times, most recently from a5f72a0 to 82d7677 Compare July 15, 2026 12:14
@binaryaaron
binaryaaron changed the base branch from binaryaaron/pr596-04-checked-typing-coverage to main July 15, 2026 12:16
@binaryaaron
binaryaaron dismissed kendrickb-nvidia’s stale review July 15, 2026 12:16

The base branch was changed.

Signed-off-by: Aaron Gonzales <aagonzales@nvidia.com>
@binaryaaron
binaryaaron force-pushed the binaryaaron/pr596-05-typecheck-tools branch from 82d7677 to b5549c2 Compare July 15, 2026 12:32
Comment thread tools/diff-lockfile.py


def _extract_source(raw: dict) -> str:
def _extract_source(raw: dict[str, Any]) -> str:
@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@binaryaaron
binaryaaron marked this pull request as ready for review July 15, 2026 20:12
@binaryaaron
binaryaaron requested a review from a team as a code owner July 15, 2026 20:12
@coderabbitai coderabbitai Bot added the chore Maintenance not tied to a user-visible change label Jul 15, 2026
@greptile-apps

greptile-apps Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR enables type checking for the tools/ directory by removing its exclusion from pyproject.toml, then adds the type annotations and structural-pattern-matching refactors needed for the tools to pass.

  • pyproject.toml: Drops ./tools/*.py from the ty exclude list so all three tool scripts are now checked.
  • tools/patch_dependabot.py: Introduces a TomlTable type alias, TypeIs-backed _is_table, and helper functions _get_table/_get_array; replaces # type: ignore[union-attr] workarounds with exhaustive match statements.
  • tools/diff-lockfile.py and tools/hf_network_guard_proxy.py: Tighten type annotations (dict[str, Any], AbstractContextManager[object]) and add @override where needed.

Confidence Score: 5/5

All changes are purely additive type annotations and equivalent refactors of existing logic; no runtime behavior is altered.

The diff is confined to type-level changes: adding annotations, introducing typed helper wrappers, and rewriting if isinstance / # type: ignore patterns as match/case with proper narrowing. The structural pattern matching in patch_dependabot.py preserves the original logic exactly, and the _extract_source rewrite in diff-lockfile.py is a strict improvement (correctly returns "" instead of None when a source key maps to None). The AbstractContextManager[object] widening in hf_network_guard_proxy.py is safe because the only extra-protocol call (.__exit__) is part of AbstractContextManager.

No files require special attention.

Important Files Changed

Filename Overview
pyproject.toml Removes ./tools/*.py from the ty type-checker exclusion list, enabling type checks on the tools directory.
tools/diff-lockfile.py Adds Any to typing imports and rewrites _extract_source to use structural pattern matching; also tightens the dict type annotation to dict[str, Any].
tools/hf_network_guard_proxy.py Adds typing-extensions>=4.15.0 dependency, widens RunningServer.server to AbstractContextManager[object] to avoid missing-import errors on Proxy, and adds @override to before_upstream_connection.
tools/patch_dependabot.py Adds TomlTable type alias, TypeIs-backed _is_table, and typed helper functions _get_table/_get_array; replaces # type: ignore comments with structural pattern matching throughout.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[pyproject.toml\nRemove tools exclusion] --> B[ty now checks tools/]

    B --> C[diff-lockfile.py]
    B --> D[hf_network_guard_proxy.py]
    B --> E[patch_dependabot.py]

    C --> C1["dict[str, Any] annotation\n_extract_source → match/case"]
    D --> D1["server: AbstractContextManager[object]\n@override on before_upstream_connection"]
    E --> E1["TomlTable TypeAlias\nTypeIs-backed _is_table\n_get_table / _get_array helpers\nmatch/case replaces # type: ignore"]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[pyproject.toml\nRemove tools exclusion] --> B[ty now checks tools/]

    B --> C[diff-lockfile.py]
    B --> D[hf_network_guard_proxy.py]
    B --> E[patch_dependabot.py]

    C --> C1["dict[str, Any] annotation\n_extract_source → match/case"]
    D --> D1["server: AbstractContextManager[object]\n@override on before_upstream_connection"]
    E --> E1["TomlTable TypeAlias\nTypeIs-backed _is_table\n_get_table / _get_array helpers\nmatch/case replaces # type: ignore"]
Loading

Reviews (1): Last reviewed commit: "chore(typecheck): include top-level tool..." | Re-trigger Greptile

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tools/diff-lockfile.py (1)

39-39: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use a read-only typed mapping instead of Any.

_extract_source only reads raw, so Mapping[str, object] models the contract more accurately, avoids unchecked Any propagation, and accepts the concrete TOML mapping passed by callers.

Suggested typing adjustment
+from collections.abc import Mapping
-from typing import Annotated, Any, Optional
+from typing import Annotated, Optional
-def _extract_source(raw: dict[str, Any]) -> str:
+def _extract_source(raw: Mapping[str, object]) -> str:

As per coding guidelines: use collection ABCs for function arguments and avoid Any when object is suitable.

Also applies to: 119-119

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 678d2ec6-1796-43a4-a17b-7bbc45f64f3b

📥 Commits

Reviewing files that changed from the base of the PR and between a321768 and b5549c2.

📒 Files selected for processing (4)
  • pyproject.toml
  • tools/diff-lockfile.py
  • tools/hf_network_guard_proxy.py
  • tools/patch_dependabot.py
💤 Files with no reviewable changes (1)
  • pyproject.toml
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{md,markdown,py}

📄 CodeRabbit inference engine (.cursor/rules/agent-markdown-style.mdc)

**/*.{md,markdown,py}: Avoid decorative bold (**text**) in list items, body text, and docstrings; use structural cues (headers, list markers, colons, backticks) for emphasis instead
Use backticks for code identifiers, paths, and CLI commands in markdown and docstrings

Files:

  • tools/diff-lockfile.py
  • tools/hf_network_guard_proxy.py
  • tools/patch_dependabot.py
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Place durable implementation guidance in function and class docstrings for public contracts and source comments for local invariants
Target Python 3.11–3.13 with modern syntax (X | Y, list[str], Self). Python 3.14+ is not supported

**/*.py: Use American English spelling in Python code, documentation, and messages.
Use Field(description=...) for every Pydantic model field.
Use assignment-style Field() by default; use Annotated only for additional metadata such as validators, constrained aliases, or discriminated unions.
Use @dataclass(frozen=True) for immutable value objects and validators; use mutable dataclasses only for builders, accumulators, and pipeline state.
Use field(default_factory=list) instead of mutable list defaults.
Use StrEnum for string-valued configuration or serialization enums and plain Enum for internal constants.
Obtain loggers with observability.get_logger(__name__); do not call logging.getLogger() or structlog.get_logger() directly.
Use .runtime, .user, and .system category loggers appropriately.
Do not use print() for operational library output; use the approved logger, click.echo(), or sys.stdout.write() where appropriate.
Use extra={} for machine-queryable logging data and f-strings only for human-readable context.
Raise errors from the custom Safe Synthesizer error hierarchy, using the documented dual inheritance for user and internal errors.
Keep shared package code compatible with Python 3.11; do not use Python 3.12-only syntax such as PEP 695 type statements or bracketed generic parameters.
Prefer X | Y, built-in collection generics, and Self over Optional, Union, and legacy typing collections.
Use collection ABCs for function arguments and concrete collection types for return values.
Use Protocol for structural subtyping and avoid Any when object, generics, or protocols are suitable.
Use TYPE_CHECKING guards for heavy imports such as pandas, torch, and transformers.
...

Files:

  • tools/diff-lockfile.py
  • tools/hf_network_guard_proxy.py
  • tools/patch_dependabot.py
**/*

📄 CodeRabbit inference engine (STYLE_GUIDE.md)

**/*: Every source file requires the SPDX copyright and license header appropriate to its file format.
End files with a newline, remove trailing whitespace, use one space between sentences, and keep code, comments, and docstrings within 120 characters.

**/*: All merged commits must use Conventional Commits format: <type>(<scope>): <description> or <type>: <description>, with a lowercase valid type and a description no longer than 100 characters.
All contributions require a DCO Signed-off-by trailer and a cryptographic commit signature.
Before submitting a pull request, run formatting, checks, and tests using mise run format, mise run check, and mise run test.
Branches other than main must use lowercase author-prefixed names in one of the documented forms, optionally including an issue ID and category.
Release tags must use a v prefix and PEP 440 stable or release-candidate versions, such as v1.0.0 or v0.1.0rc0; alpha versions and dashed -rc suffixes are not used.
Do not move a published release tag; create and validate a new release candidate when code changes.
Use mise run <task> for project tasks; the Makefile only bootstraps mise and provides deprecated compatibility messages.

Files:

  • tools/diff-lockfile.py
  • tools/hf_network_guard_proxy.py
  • tools/patch_dependabot.py

⚙️ CodeRabbit configuration file

**/*: Review as a senior maintainer for NeMo Safe Synthesizer. Prioritize issues that can change behavior, break user workflows, weaken privacy guarantees, hide failures, make tests unreliable, or create maintenance risk. Avoid generic style commentary unless it points to a concrete project convention that automated tools will not catch.
Comment only when the finding is actionable and tied to changed code. For each finding, state the impact, the condition that triggers it, and the smallest practical fix. Prefer one precise comment over broad advice. Do not ask for refactors outside the PR scope unless the changed code creates the problem.
Review type guidance: - Potential issue: use for correctness bugs, data loss, privacy leaks,
security risks, broken public APIs, invalid config behavior, missing
validation, hidden failures, nondeterministic tests, or CI breakage.

  • Refactor suggestion: use for local maintainability problems introduced
    by the diff when they have clear future cost, such as duplicated setup,
    unclear boundaries, over-mocking, avoidable complexity, or opaque test
    helpers.
  • Nitpick: avoid in chill mode. Do not emit formatting, import-order,
    wording, or style-only comments unless automated tools cannot catch the
    issue and it affects maintainability.

Severity guidance: - Critical: security/privacy leaks, data loss, training/test/holdout
contamination, or broken release/package/core pipeline execution.

  • Major: incorrect generation/training/evaluation behavior, broken
    CLI/SDK public API, invalid config defaults or validators, or GPU/vLLM
    cleanup and process-isolation bugs likely to fail CI or production
    runs.
  • Minor: localized bugs, missing focused tests for changed behavior, or
    bad test patterns that weaken regression coverage.
  • Trivial: small cleanup with no behavior impact. Usually suppress in
    chill mode.
  • Info: context only. Avoid unless it helps reviewers understand risk.
    Safe-Synthesizer-specific review focus: - Data ...

Files:

  • tools/diff-lockfile.py
  • tools/hf_network_guard_proxy.py
  • tools/patch_dependabot.py
**/*.{py,sh,yaml,yml,md}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

All source files with .py, .sh, .yaml, .yml, or .md extensions must include SPDX copyright headers, except files listed in .copyrightignore.

Files:

  • tools/diff-lockfile.py
  • tools/hf_network_guard_proxy.py
  • tools/patch_dependabot.py
tools/**

⚙️ CodeRabbit configuration file

Review tools as developer and CI infrastructure. Check that scripts use uv or Makefile wrappers instead of ad hoc python/pip commands, preserve read-only behavior for check targets, fail with clear messages, avoid hidden network or filesystem side effects, and stay consistent with STYLE_GUIDE.md and CONTRIBUTING.md. Tooling may use print() when it is a standalone script or intentional CLI output.

Files:

  • tools/diff-lockfile.py
  • tools/hf_network_guard_proxy.py
  • tools/patch_dependabot.py
🔇 Additional comments (15)
tools/patch_dependabot.py (8)

10-10: LGTM!


34-58: LGTM!


130-195: LGTM!


236-256: LGTM!


274-274: LGTM!


291-302: LGTM!


322-324: LGTM!

Also applies to: 336-336


366-382: LGTM!

tools/hf_network_guard_proxy.py (5)

11-11: LGTM!


78-78: LGTM!


94-94: LGTM!


175-175: LGTM!


206-207: LGTM!

tools/diff-lockfile.py (2)

121-123: LGTM!


126-129: LGTM!

Comment thread tools/diff-lockfile.py
Comment on lines +124 to +125
case dict():
return ""

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' 'Lockfile source shapes:'
rg -n '^\s*source\s*=\s*\{' --glob 'uv.lock' --glob '**/uv.lock' || true

printf '%s\n' 'Parser tests and usages:'
rg -n '_extract_source|parse_packages' --glob '*.py' || true

Repository: NVIDIA-NeMo/Safe-Synthesizer

Length of output: 190


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- tools/diff-lockfile.py outline ---'
ast-grep outline tools/diff-lockfile.py --view expanded || true

printf '%s\n' '--- relevant lines around _extract_source and parse_packages ---'
sed -n '1,260p' tools/diff-lockfile.py | cat -n

printf '%s\n' '--- lockfiles containing source tables ---'
rg -n '^\s*source\s*=\s*\{' --glob 'uv.lock' --glob '**/uv.lock' . || true

printf '%s\n' '--- usages/tests for duplicate keys or source extraction ---'
rg -n 'parse_packages|_extract_source|name@source|source\]' tools test . || true

Repository: NVIDIA-NeMo/Safe-Synthesizer

Length of output: 36307


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
from collections import defaultdict
from pathlib import Path
import tomllib

lock = tomllib.loads(Path("uv.lock").read_text())

packages = lock.get("package", [])
by_name = defaultdict(list)

source_shapes = defaultdict(int)
for pkg in packages:
    name = pkg.get("name")
    source = pkg.get("source")
    if isinstance(source, dict):
        source_shapes[tuple(sorted(source.keys()))] += 1
    by_name[name].append((pkg.get("version"), source))

print("unique source key sets:")
for keys, count in sorted(source_shapes.items(), key=lambda kv: (len(kv[0]), kv[0])):
    print(f"{count:4d}  {keys}")

print("\nduplicate package names with distinct source reprs:")
for name, items in sorted(by_name.items()):
    if len(items) > 1:
        uniq = []
        seen = set()
        for version, source in items:
            rep = (version, repr(source))
            if rep not in seen:
                seen.add(rep)
                uniq.append((version, source))
        if len(uniq) > 1:
            print(f"\n{name}:")
            for version, source in uniq:
                print(f"  version={version!r} source={source!r}")
PY

Repository: NVIDIA-NeMo/Safe-Synthesizer

Length of output: 2601


Keep package variants distinct in parse_packages. name@source still collapses multiple [[package]] entries that share the same name and source, so later versions overwrite earlier ones and the lockfile diff can miss dependency changes. Include version in the key or store all variants per package name/source.

Source: Path instructions

@binaryaaron
binaryaaron added this pull request to the merge queue Jul 16, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 16, 2026
@binaryaaron
binaryaaron added this pull request to the merge queue Jul 17, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants