chiark / gitweb /
documentation/python: properly handle invalid annotation types.
authorVladimír Vondruš <mosra@centrum.cz>
Sun, 14 Jul 2019 10:51:25 +0000 (12:51 +0200)
committerVladimír Vondruš <mosra@centrum.cz>
Sun, 14 Jul 2019 17:11:08 +0000 (19:11 +0200)
Such as using a tuple instead of Tuple or putting a function there
instead of a type.

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

index 38b3532fdde33c6a3c1c9b8aca1049cc534846ac..2b03d11d2905783c2bde7c5d2ed546363deacc79 100755 (executable)
@@ -773,7 +773,7 @@ def extract_annotation(state: State, referrer_path: List[str], annotation) -> st
     # If the annotation is from the typing module, it could be a "bracketed"
     # type, in which case we want to recurse to its types as well. Otherwise
     # just get its name.
-    elif annotation.__module__ == 'typing':
+    elif hasattr(annotation, '__module__') and annotation.__module__ == 'typing':
         if sys.version_info >= (3, 7):
             name = annotation._name
         elif annotation is typing.Any:
@@ -785,6 +785,12 @@ def extract_annotation(state: State, referrer_path: List[str], annotation) -> st
         else:
             return 'typing.' + name
 
+    # Things like (float, int) instead of Tuple[float, int] or using np.array
+    # instead of np.ndarray. Ignore with a warning.
+    elif not isinstance(annotation, type):
+        logging.warning("invalid annotation %s in %s, ignoring", annotation, '.'.join(referrer_path))
+        return None
+
     # Otherwise it's a plain type. Turn it into a link.
     return make_name_link(state, referrer_path, map_name_prefix(state, extract_type(annotation)))
 
index f7d3b198f3e501197c7a9d16e19b51faa6e124e0..070c54910a65c95ec3964587403f68e72c26a7f1 100644 (file)
               third: str = &#x27;hello&#x27;) -&gt; <a href="inspect_annotations.Foo.html" class="m-doc">Foo</a></span>
             </dt>
             <dd>An annotated function</dd>
+            <dt>
+              <span class="m-doc-wrap-bumper">def <a href="#annotation_func_instead_of_type" class="m-doc-self" id="annotation_func_instead_of_type">annotation_func_instead_of_type</a>(</span><span class="m-doc-wrap">a)</span>
+            </dt>
+            <dd>Annotation with a function instead of a type, ignored</dd>
+            <dt>
+              <span class="m-doc-wrap-bumper">def <a href="#annotation_tuple_instead_of_tuple" class="m-doc-self" id="annotation_tuple_instead_of_tuple">annotation_tuple_instead_of_tuple</a>(</span><span class="m-doc-wrap">a)</span>
+            </dt>
+            <dd>Annotation with a tuple instead of Tuple, ignored</dd>
             <dt>
               <span class="m-doc-wrap-bumper">def <a href="#args_kwargs" class="m-doc-self" id="args_kwargs">args_kwargs</a>(</span><span class="m-doc-wrap">a, b, *args, **kwargs)</span>
             </dt>
index fbf143fc92a8939b43cc9def850fb1585fc8f3ad..bde1f3e934ac04ab083d910dcc3defedb2b33eba 100644 (file)
@@ -30,6 +30,12 @@ def partial_annotation(foo, param: Tuple[int, int], unannotated, cls: Foo):
     """Partially annotated function"""
     pass
 
+def annotation_tuple_instead_of_tuple(a: (float, int)):
+    """Annotation with a tuple instead of Tuple, ignored"""
+
+def annotation_func_instead_of_type(a: open):
+    """Annotation with a function instead of a type, ignored"""
+
 # Only possible with native code now, https://www.python.org/dev/peps/pep-0570/
 #def positionals_only(positional_only, /, positional_kw):
     #"""Function with explicitly delimited positional args"""