Skip to content

NamedTuples can't match Protocols with Callable fields #6575

@FuegoFro

Description

@FuegoFro

This looks like a bug that is a combination of how NamedTuple fields are created and how node types are determined.

If a Protocol expects a field with type Callable, passing a NamedTuple that has a Callable field won't work. A minimal reproduction is below. This behavior happens for me with Python 3.7.2 and mypy 0.680+dev.4e0a1583aeb00b248e187054980771f1897a1d31 using only the --strict flag.

from typing import Callable, NamedTuple

from typing_extensions import Protocol


class A(NamedTuple):
    my_func: Callable[[], str]


class WithFunc(Protocol):
    # This is a property so it matches the read-only `my_func` in the NamedTuple
    @property
    def my_func(self) -> Callable[[], str]:
        ...


def call_func(with_func: WithFunc) -> None:
    print(with_func.my_func())


a = A(lambda: "hi")
call_func(a)  # <-- PROBLEM: This says that `A#my_func` has type `str`

MYPY = False
if MYPY:
    reveal_type(a.my_func)  # This correctly identifies `A#my_func` as a function

It looks like this is due to an interaction between the find_node_type code that handles properties and the build_namedtuple_typeinfo code which implicitly marks all NamedTuple fields as properties. This causes the find_node_type code to think that the field has the type of the Callable's return type, rather than the whole Callable.

I'm happy to submit a PR to try to fix this, but it's unclear to me if the right solution here is to no longer assume that all NamedTuple are properties or to add an explicit check for NamedTuples to the property-resolving code in find_node_type. Or something else entirely! If you have suggestions for the best way to resolve this I can submit a PR 🙂

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy