Skip to content

[ty] Use a more lenient fallback type for failed namedtuple() and NamedTuple calls#22765

Merged
AlexWaygood merged 1 commit intomainfrom
alex/lenient-namedtuple-parsing-2
Jan 21, 2026
Merged

[ty] Use a more lenient fallback type for failed namedtuple() and NamedTuple calls#22765
AlexWaygood merged 1 commit intomainfrom
alex/lenient-namedtuple-parsing-2

Conversation

@AlexWaygood
Copy link
Member

Summary

This is stacked on top of #22718; review that first.

Currently if a user makes a bad NamedTuple() call like this:

from typing import NamedTuple, reveal_type

Bad1 = NamedTuple()
Bad1()

then we emit errors on both calls: one correct error for the bad NamedTuple() call (it's missing required arguments), and then another spurious error on the Bad1() call:

No overload of bound method `__init__` matches arguments

The reason for this second, spurious error is that we inferred type[NamedTupleFallback] for the result of the Bad1() call, and NamedTupleFallback has this __init__ signature, which isn't appropriate in this context -- it actually reflects the arguments you need to pass to the NamedTuple function itself in order to create a NamedTuple class, not the signature of the constructors that all NamedTuple classes have:

@overload
def __init__(self, typename: str, fields: Iterable[tuple[str, Any]], /) -> None: ...
@overload
@typing_extensions.deprecated(
"Creating a typing.NamedTuple using keyword arguments is deprecated and support will be removed in Python 3.15"
)
def __init__(self, typename: str, fields: None = None, /, **kwargs: Any) -> None: ...

This PR updates the fallback type we use when NamedTuple parsing fails, so that it's more lenient and the spurious error is no longer emitted.

Test Plan

mdtests updated

@AlexWaygood AlexWaygood added the ty Multi-file analysis & type inference label Jan 20, 2026
Comment on lines -6596 to +6615
let find_keyword = |name: &str| -> Option<&ast::Keyword> {
keywords
.iter()
.find(|kw| kw.arg.as_ref().is_some_and(|arg| arg.id.as_str() == name))
};
let typename_kw = find_keyword("typename");
let field_names_kw = find_keyword("field_names");
let typename_kw = call_expr.arguments.find_keyword("typename");
let field_names_kw = call_expr.arguments.find_keyword("field_names");
Copy link
Member Author

@AlexWaygood AlexWaygood Jan 20, 2026

Choose a reason for hiding this comment

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

drive-by simplification; no functional change to this bit

@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 20, 2026

Typing conformance results

No changes detected ✅

@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 20, 2026

mypy_primer results

Changes were detected when running on open source projects
prefect (https://github.com/PrefectHQ/prefect)
- src/integrations/prefect-dbt/prefect_dbt/cli/commands.py:461:21: error[invalid-await] `Unknown | None | Coroutine[Any, Any, None | Unknown]` is not awaitable
+ src/integrations/prefect-dbt/prefect_dbt/cli/commands.py:461:21: error[invalid-await] `Unknown | None | Coroutine[Any, Any, Unknown | None]` is not awaitable
- src/integrations/prefect-dbt/prefect_dbt/cli/commands.py:535:21: error[invalid-await] `Unknown | None | Coroutine[Any, Any, None | Unknown]` is not awaitable
+ src/integrations/prefect-dbt/prefect_dbt/cli/commands.py:535:21: error[invalid-await] `Unknown | None | Coroutine[Any, Any, Unknown | None]` is not awaitable
- src/integrations/prefect-dbt/prefect_dbt/cli/commands.py:610:21: error[invalid-await] `Unknown | None | Coroutine[Any, Any, None | Unknown]` is not awaitable
+ src/integrations/prefect-dbt/prefect_dbt/cli/commands.py:610:21: error[invalid-await] `Unknown | None | Coroutine[Any, Any, Unknown | None]` is not awaitable
- src/integrations/prefect-dbt/prefect_dbt/cli/commands.py:685:21: error[invalid-await] `Unknown | None | Coroutine[Any, Any, None | Unknown]` is not awaitable
+ src/integrations/prefect-dbt/prefect_dbt/cli/commands.py:685:21: error[invalid-await] `Unknown | None | Coroutine[Any, Any, Unknown | None]` is not awaitable
- src/integrations/prefect-dbt/prefect_dbt/cli/commands.py:760:21: error[invalid-await] `Unknown | None | Coroutine[Any, Any, None | Unknown]` is not awaitable
+ src/integrations/prefect-dbt/prefect_dbt/cli/commands.py:760:21: error[invalid-await] `Unknown | None | Coroutine[Any, Any, Unknown | None]` is not awaitable
- src/integrations/prefect-dbt/prefect_dbt/cli/commands.py:835:21: error[invalid-await] `Unknown | None | Coroutine[Any, Any, None | Unknown]` is not awaitable
+ src/integrations/prefect-dbt/prefect_dbt/cli/commands.py:835:21: error[invalid-await] `Unknown | None | Coroutine[Any, Any, Unknown | None]` is not awaitable

scikit-build-core (https://github.com/scikit-build/scikit-build-core)
- src/scikit_build_core/build/wheel.py:99:20: error[no-matching-overload] No overload of bound method `__init__` matches arguments
- Found 47 diagnostics
+ Found 46 diagnostics

No memory usage changes detected ✅

@AlexWaygood AlexWaygood force-pushed the alex/lenient-namedtuple-parsing-2 branch from e1cd316 to 384c240 Compare January 20, 2026 14:50
Copy link
Member

@charliermarsh charliermarsh left a comment

Choose a reason for hiding this comment

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

Seems reasonable (assuming tests pass and ecosystem changes are clean).

@AlexWaygood AlexWaygood marked this pull request as ready for review January 20, 2026 14:54
Base automatically changed from alex/defer-namedtuple to main January 21, 2026 16:03
@AlexWaygood AlexWaygood force-pushed the alex/lenient-namedtuple-parsing-2 branch from 384c240 to 045c288 Compare January 21, 2026 16:08
@AlexWaygood AlexWaygood enabled auto-merge (squash) January 21, 2026 16:09
@AlexWaygood AlexWaygood merged commit 22f240d into main Jan 21, 2026
46 of 48 checks passed
@AlexWaygood AlexWaygood deleted the alex/lenient-namedtuple-parsing-2 branch January 21, 2026 16:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants