title: Get Type Argument of Arbitrarily High Generic Parent Class at Runtime
body: <p>Given this:</p>
  <pre><code>from typing import Generic, TypeVar
  
  T = TypeVar('T')
  
  class Parent(Generic[T]):
      pass
  </code></pre>
  <p>I can get <code>int</code> from <code>Parent[int]</code> using <code>typing.get_args(Parent[int])[0]</code>.</p>
  <p>The problem becomes a bit more complicated with the following:</p>
  <pre><code>class Child1(Parent[int]):
      pass
  
  class Child2(Child1):
      pass
  </code></pre>
  <p>To support an arbitrarily long inheritance hierarchy, I made the below solution:</p>
  <pre><code>import typing
  from dataclasses import dataclass
  
  @dataclass(frozen=True)
  class Found:
      value: Any
  
  def get_parent_type_parameter(child: type) -&gt; Optional[Found]:
      for base in child.mro():
          # If no base classes of `base` are generic, then `__orig_bases__` is nonexistent causing an `AttributeError`.
          # Instead, we want to skip iteration.
          for generic_base in getattr(base, &quot;__orig_bases__&quot;, ()):
              if typing.get_origin(generic_base) is Parent:
                  [type_argument] = typing.get_args(generic_base)
  
                  # Return `Found(type_argument)` instead of `type_argument` to differentiate between `Parent[None]` 
                  # as a base class and `Parent` not appearing as a base class.
                  return Found(type_argument)
  
      return None
  </code></pre>
  <p>such that <code>get_parent_type_parameter(Child2)</code> returns <code>int</code>. I am only interested in the type argument of one particular base class (<code>Parent</code>), so I've hardcoded that class into <code>get_parent_type_parameter</code> and ignore any other base classes.</p>
  <p>But my above solution breaks down with chains like this:</p>
  <pre><code>class Child3(Parent[T], Generic[T]):
      pass
  </code></pre>
  <p>where <code>get_parent_type_parameter(Child3[int])</code> returns <code>T</code> instead of <code>int</code>.</p>
  <p>While any answers that tackle <code>Child3</code> are already great, being able to deal with situations like <code>Child4</code> would be even better:</p>
  <pre><code>from typing import Sequence
  
  class Child4(Parent[Sequence[T]], Generic[T]):
      pass
  </code></pre>
  <p>so <code>get_parent_type_parameter(Child4[int])</code> returns <code>Sequence[int]</code>.</p>
  <p><strong>Is there a more robust way of accessing the type argument of a class <code>X</code> at runtime given an annotation <code>A</code> where <code>issubclass(typing.get_origin(A), X)</code> is <code>True</code>?</strong></p>
  <p>Why I need this:</p>
  <p>Recent Python HTTP frameworks generate the endpoint documentation (and response schema) from the function's annotated return type. For example:</p>
  <pre><code>app = ...
  
  @dataclass
  class Data:
      hello: str
  
  @app.get(&quot;/&quot;)
  def hello() -&gt; Data:
      return Data(hello=&quot;world&quot;)
  </code></pre>
  <p>I am trying to expand this to account for status code and other non-body components:</p>
  <pre><code>@dataclass
  class Error:
      detail: str
  
  class ClientResponse(Generic[T]):
      status_code: ClassVar[int]
      body: T
  
  class OkResponse(ClientResponse[Data]):
      status_code: ClassVar[int] = 200
  
  class BadResponse(ClientResponse[Error]):
      status_code: ClassVar[int] = 400
  
  @app.get(&quot;/&quot;)
  def hello() -&gt; Union[OkResponse, BadResponse]:
      if random.randint(1, 2) == 1:
          return OkResponse(Data(hello=&quot;world&quot;))
  
      return BadResponse(Error(detail=&quot;a_custom_error_label&quot;))
  </code></pre>
  <p>To generate the <a href="https://swagger.io/specification/" rel="nofollow noreferrer">OpenAPI</a> documentation, my framework would evaluate <code>get_parent_type_parameter(E)</code> (with <code>ClientResponse</code> hardcoded as the parent in <code>get_parent_type_parameter</code>) on each <code>E</code> within the <code>Union</code> after inspecting the annotated return type of the function passed to <code>app.get</code>. So <code>E</code> would be <code>OkResponse</code> first resulting in <code>Data</code>. Then it would be <code>ErrorResponse</code>, resulting in <code>Error</code>. My framework then iterates through the <code>__annotations__</code> of each of the <code>body</code> types and generates the response schema in the documentation for the client.</p>