microsoft / microsoft/pyright

Member access on an Annotated alias value is rejected (unlike __getitem__, cf #8916)

Open
#11,538 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
15.6k
Forks
1.8k
Avg merge
12h 13m
Merged PRs (30d)
52

Description

Describe the bug

Accessing a member on an Annotated[...] alias used as a value raises reportAttributeAccessIssue, even though:

  • at runtime it resolves — typing._AnnotatedAlias.__getattr__ delegates attribute access to the annotated type (__origin__);
  • the analogous __getitem__ case on an Annotated alias was special-cased in #8916 (fixed in 1.1.380);
  • in a type position the same alias unfolds correctly to the underlying type.

It came up with a FastAPI-style pattern: a Depends alias Service = Annotated[_Service, Depends(...)] is also used to read a ClassVar on the service (Service.some_endpoint). mypy accepts it.

Code or Screenshots

Pyright playground

from typing import Annotated

class Foo:
    bar: int = 42

A = Annotated[Foo, "meta"]        # an `Annotated` alias (e.g. a FastAPI `Depends` alias)

reveal_type(A)                    # "Annotated"  -> value not unfolded to type[Foo]
A.bar                             # error: Cannot access attribute "bar" for class "Annotated"

def f(x: A) -> int:               # in a *type* position, Annotated unfolds correctly:
    reveal_type(x)                # "Foo"
    return x.bar                  # OK

reveal_type(A) is "Annotated" (the special form), not type[Foo], so A.bar fails — while the same alias in a type position reveals Foo and x.bar is fine. Runtime resolves it fine (Annotated[Foo, "m"].bar is Foo.bar -> True).

VS Code extension or command-line

pyright 1.1.411, CLI, default settings. mypy reports no error on the same file.

Additional context

Same "special form in a value expression" category as #8916 (which special-cased __getitem__). Since _AnnotatedAlias is an undocumented private class, that thread chose to permit the operation — would it make sense to extend the special-casing to member access? Happy to hear if this is intended / a gray area.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the minimal Annotated example in the issue and compare member access with the existing __getitem__ handling from #8916. Trace the checker’s special-form handling for an Annotated alias used as a value, while preserving its current behavior in type positions. Done means A.bar no longer reports an attribute-access error and the shown reveal_type results remain valid.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devtools
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.