Skip to content

Meta issue: better getattr support #11142

Open
@sobolevn

Description

@sobolevn

Feature

One thing that bothered me for a long time is getattr and its very broad return type even for simplest cases:

from typing import Literal

class Some:
    def __init__(self) -> None:
        self.a = 1

s = Some()

reveal_type(s.a)  # Revealed type is "builtins.int"
reveal_type(getattr(s, 'a'))  # Revealed type is "Any"
reveal_type(getattr(s, 'b'))  # Revealed type is "Any"
reveal_type(getattr(s, 'a', None))  # Revealed type is "Union[Any, None]"

a: Literal['a']
reveal_type(getattr(s, a))  # Revealed type is "Any"

ab: Literal['a', 'b']
reveal_type(getattr(s, ab))  # Revealed type is "Any"

So, I propose to add better support for it to mypy.

The same example, after the support is added:

from typing import Literal

class Some:
    def __init__(self) -> None:
        self.a = 1

s = Some()

reveal_type(s.a)  # Revealed type is "builtins.int"
reveal_type(getattr(s, 'a'))  # Revealed type is "builtins.int"
reveal_type(getattr(s, 'b'))  # error: "Some" has no attribute "b"
reveal_type(getattr(s, 'a', None))  # Revealed type is "builtins.int"

a: Literal['a']
reveal_type(getattr(s, a))  # Revealed type is "builtins.int"

ab: Literal['a', 'b']
reveal_type(getattr(s, ab))  # error: "Some" has no attribute "b"
reveal_type(getattr(s, ab, None))  # Revealed type is "builtins.int | None"

I have even written a custom plugin for it at some point.

Why?

This pattern is quite popular among Python developers. geattr(obj, 'string_key', None) is used for compatibility, optional dependencies, etc. That's something you can find in almost any project.

Technical details

I am going to utilize existing checkmember logic.
I even plan to support attribute plugins, where possible, because a.x and getattr(a, 'x') are semantically identical.
For now only str literals and Literal str types are going to be supported.

Related issues and problems

I am calling this issue "meta", because there are several very related problems I want to mention / solve here:

Next steps

I will start with a PR with a code prototype in a couple of days.

Metadata

Metadata

Assignees

No one assigned

    Labels

    featuremetaIssues tracking a broad area of work

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions