What is the right way to extract PEP 593 annotation information attached with Annotated[] from a class/type object?
I want to annotate the members of a class to indicate how to process objects of the class. Ideally I’d like to use a TypedDict as the base class for this.
There’s a suggestion here to use a mix of typing.get_origin and typing.get_args which looked promising.
But this doesn’t seem to play nicely with PEP 655 Required[] and NotRequired[].  Specifically PEP 655 states:
Required[]andNotRequired[]can be used withAnnotated[], in any nesting order
This means that get_origin could return Required and the Annotated might come from get_args or visa versa, or any mix of those.
I can write a function to iterate down those three specific wrappers but this leaves be with two concerns:
- Is this list of wrappers a closed set? will future versions of python add more? PEP 593 was python 3.9 and PEP 655 was Python 3.11 so I guess this is really not future proof.
- Am I re-inventing the wheel? PEP 593 seems to talk about how to annotate but doesn’t describe how to extract information from annotations. Am I missing something obvious here?
The iteration may look something like this:
while get_origin(foo) in (Required, NotRequired):
    foo = get_args(foo)[0]
But this will obviously break the moment a PEP adds a fourth thing.
Worked Example:
from typing import TypedDict, Annotated, NamedTuple
class ExtractFrom(NamedTuple):
    name: str
    source_id: int
class UsefulInfo(TypedDict):
    a: Raquired[Annotated[int, ExtractFrom("x", 1)]]
    b: Annotated[Required[int], ExtractFrom("y", 2)]
    c: Annotated[int, ExtractFrom("z", 3)]
Given this definition, all I really want is code that will search for ExtractFrom instances and give me a dictionary:
{
    "a": ExtractFrom("x", 1),
    "b": ExtractFrom("y", 2),
    "c": ExtractFrom("c", 3),
}
I feel like I must be over thinking this and missing something obvious.