SIGH.
if hasattr(annotation, '__origin__') and annotation.__origin__ is typing.Union:
# FOR SOME REASON `annotation.__args__[1] is None` is always False,
# so we have to use isinstance(). HOWEVER, we *can't* use
- # isinstance if it's a "bracketed" type -- it'll die. So check that
- # first.
- if len(annotation.__args__) == 2 and not hasattr(annotation.__args__[1], '__args__') and isinstance(None, annotation.__args__[1]):
+ # isinstance if:
+ # - it's a "bracketed" type, having __args__
+ # (see the `annotation_union_second_bracketed()` test)
+ # - it's a ForwardRef because get_type_hints_or_nothing() failed
+ # due to a type error (see the `annotation_union_of_undefined()`
+ # test)
+ # because it'll die. So check that first.
+ if (len(annotation.__args__) == 2 and
+ not hasattr(annotation.__args__[1], '__args__') and
+ # Same 3.6 ForwardRef workaround as above
+ not isinstance(annotation.__args__[1], typing.ForwardRef if sys.version_info >= (3, 7) else typing._ForwardRef) and
+ isinstance(None, annotation.__args__[1])
+ ):
name = 'typing.Optional'
args = annotation.__args__[:1]
else:
<span class="m-doc-wrap-bumper">def <a href="#annotation_union" class="m-doc-self">annotation_union</a>(</span><span class="m-doc-wrap">a: typing.Union[float, int])</span>
</dt>
<dd>Annotation with the Union type</dd>
+ <dt id="annotation_union_of_undefined">
+ <span class="m-doc-wrap-bumper">def <a href="#annotation_union_of_undefined" class="m-doc-self">annotation_union_of_undefined</a>(</span><span class="m-doc-wrap">a: typing.Union[int, something.Undefined])</span>
+ </dt>
+ <dd>Annotation with an union that has an undefined type inside, where we can't use isinstance either</dd>
<dt id="annotation_union_second_bracketed">
<span class="m-doc-wrap-bumper">def <a href="#annotation_union_second_bracketed" class="m-doc-self">annotation_union_second_bracketed</a>(</span><span class="m-doc-wrap">a: typing.Union[float, typing.List[int]])</span>
</dt>
def annotation_union(a: Union[float, int]):
"""Annotation with the Union type"""
+def annotation_optional(a: Optional[float]):
+ """Annotation with the Optional type"""
+
+def annotation_union_second_bracketed(a: Union[float, List[int]]):
+ """Annotation with the Union type and second type bracketed, where we can't use isinstance"""
+
+def annotation_union_of_undefined(a: Union[int, 'something.Undefined']):
+ """Annotation with an union that has an undefined type inside, where we can't use isinstance either"""
+
def annotation_list_noparam(a: List):
"""Annotation with the unparametrized List type. 3.7 adds an implicit TypeVar to it, 3.6 not, emulate that to make the test pass on older versions"""
if sys.version_info < (3, 7):
def annotation_generic(a: List[_T]) -> _T:
"""Annotation with a generic type"""
-def annotation_optional(a: Optional[float]):
- """Annotation with the Optional type"""
-
-def annotation_union_second_bracketed(a: Union[float, List[int]]):
- """Annotation with the Union type and second type bracketed, where we can't use isinstance"""
-
def annotation_callable(a: Callable[[float, int], str]):
"""Annotation with the Callable type"""