chiark / gitweb /
documentation/python: pile on more workarounds for typing.Union.
authorVladimír Vondruš <mosra@centrum.cz>
Thu, 8 Oct 2020 10:51:18 +0000 (12:51 +0200)
committerVladimír Vondruš <mosra@centrum.cz>
Thu, 8 Oct 2020 11:11:01 +0000 (13:11 +0200)
SIGH.

documentation/python.py
documentation/test_python/inspect_annotations/inspect_annotations.html
documentation/test_python/inspect_annotations/inspect_annotations.py

index 48b0bd6f3724d374389fbae9f6f5ad5231cfd32a..af89bfd98fa90d3158764b4ae3c9834b2fe5cfcc 100755 (executable)
@@ -1147,9 +1147,19 @@ def extract_annotation(state: State, referrer_path: List[str], annotation) -> Tu
         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:
index f827525126114f2ccd8d5f1b02f34cc506681573..494ccc15eaf4b6c9ba57050cae4b5046b7a5158c 100644 (file)
               <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&#x27;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>
index 11802cb018ca4393a7bb749aebf34c049d2f5716..c9b1cf20c770141b2540e78a80ddea4fc9d8c0a3 100644 (file)
@@ -65,6 +65,15 @@ def annotation_any(a: Any):
 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):
@@ -73,12 +82,6 @@ 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"""