Skip to content

Conversation

@ValdonVitija
Copy link
Contributor

@ValdonVitija ValdonVitija commented Dec 26, 2025

Summary

Fixes false positive in ARG001 when **kwargs is passed to typing.TypeVar

Closes #22178

When **kwargs is used in a typing.TypeVar call, the checker was not recognizing it as a usage, leading to false positive "unused function argument" warnings.

Root Cause

In the AST, keyword arguments are represented by the Keyword struct with an arg field of type Option<Identifier>:

  • Named keywords like bound=int have arg = Some("bound")
  • Dictionary unpacking like **kwargs has arg = None

The existing code only handled the Some(id) case, never visiting the expression when arg was None, so **kwargs was never marked as used.

Changes

Added an else branch to handle **kwargs unpacking by calling visit_non_type_definition(value) when arg is None. This ensures the kwargs variable is properly visited and marked as used by the semantic model.

Test Plan

Tested with the following code:

import typing

def f(
    *args: object,
    default: object = None,
    **kwargs: object,
) -> None:
    typing.TypeVar(*args, **kwargs)

Before :

ARG001 Unused function argument: kwargs

After :

All checks passed!

Run the example with the following command(from the root of ruff and please change the path to the module that contains the code example):

cargo run -p ruff -- check /path/to/file.py --isolated --select=ARG --no-cache

@astral-sh-bot
Copy link

astral-sh-bot bot commented Dec 29, 2025

ruff-ecosystem results

Linter (stable)

ℹ️ ecosystem check detected linter changes. (+1 -0 violations, +0 -0 fixes in 1 projects; 54 projects unchanged)

scikit-build/scikit-build-core (+1 -0 violations, +0 -0 fixes)

+ src/scikit_build_core/_compat/typing.py:36:32: RUF100 [*] Unused `noqa` directive (unused: `ARG001`)

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
RUF100 1 1 0 0 0

Linter (preview)

ℹ️ ecosystem check detected linter changes. (+1 -0 violations, +0 -0 fixes in 1 projects; 54 projects unchanged)

scikit-build/scikit-build-core (+1 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --no-fix --output-format concise --preview

+ src/scikit_build_core/_compat/typing.py:36:32: RUF100 [*] Unused `noqa` directive (unused: `ARG001`)

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
RUF100 1 1 0 0 0

Copy link
Contributor

@ntBre ntBre left a comment

Choose a reason for hiding this comment

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

Thank you! This is exactly the fix I had in mind.

Could you add your manual test case from the PR summary as a new ARG001 case just to prevent future regressions?

You could add it at the bottom of this file:

class C:
def f(self, x, y):
"""Docstring."""
msg = t"{x}..."
raise NotImplementedError(msg)

Comment on lines 1877 to 1878
// The only case when a keyword argument is None is when using **kwargs, since there is no explicit 'arg' name for it.
// Ex: typing.TypeVar(*args, **kwargs)
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure we need the first part of this comment, but I like the example.

Suggested change
// The only case when a keyword argument is None is when using **kwargs, since there is no explicit 'arg' name for it.
// Ex: typing.TypeVar(*args, **kwargs)
// Ex: typing.TypeVar(**kwargs)

I just removed the *args to make it even more clear which part is relevant.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ntBre Added the required test case & removed the first part of the comment.

Thank you!

@ntBre ntBre added the bug Something isn't working label Dec 29, 2025
Copy link
Contributor

@ntBre ntBre left a comment

Choose a reason for hiding this comment

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

Thank you!

@ntBre ntBre changed the title Typevar does not recognize kwargs for arg001 [flake8-unused-arguments] Mark **kwargs in TypeVar as used (ARG001) Dec 31, 2025
@ntBre ntBre merged commit 77c2f4c into astral-sh:main Dec 31, 2025
40 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TypeVar special handling doesn't recognize ** for ARG001

2 participants