chiark / gitweb /
documentation/python: correctly link all type annotations as well.
authorVladimír Vondruš <mosra@centrum.cz>
Sat, 24 Aug 2019 07:50:22 +0000 (09:50 +0200)
committerVladimír Vondruš <mosra@centrum.cz>
Sun, 25 Aug 2019 10:47:45 +0000 (12:47 +0200)
documentation/python.py
documentation/test_python/inspect_type_links/inspect_type_links.second.Foo.html
documentation/test_python/inspect_type_links/inspect_type_links.second.FooSlots.html
documentation/test_python/inspect_type_links/inspect_type_links.second.FooSlotsInvalid.html
documentation/test_python/inspect_type_links/inspect_type_links.second.html
documentation/test_python/inspect_type_links/inspect_type_links/second.py
documentation/test_python/pybind_type_links/pybind_type_links.Foo.html
documentation/test_python/pybind_type_links/pybind_type_links.html
documentation/test_python/test_pybind.py

index c57d0eacaf7b8331706af0c0b7ecad2997e83b08..dabfc69a964c6d64b255188ef11381fa5390e758 100755 (executable)
@@ -615,9 +615,10 @@ def parse_pybind_type(state: State, referrer_path: List[str], signature: str) ->
         input_type = match.group(0)
         signature = signature[len(input_type):]
         # Prefix types with the typing module to be consistent with pure
-        # Python annotations
+        # Python annotations and allow them to be linked to
         if input_type in ['Callable', 'Dict', 'List', 'Optional', 'Set', 'Tuple', 'Union']:
-            type = type_link = 'typing.' + input_type
+            type = 'typing.' + input_type
+            type_link = make_name_link(state, referrer_path, type)
         else:
             type = map_name_prefix(state, input_type)
             type_link = make_name_link(state, referrer_path, type)
@@ -889,19 +890,22 @@ def extract_annotation(state: State, referrer_path: List[str], annotation) -> st
             logging.warning("can't inspect annotation %s for %s, falling back to a string representation", annotation, '.'.join(referrer_path))
             return str(annotation)
 
+        # Add type links to name
+        name_link = make_name_link(state, referrer_path, name)
+
         # Arguments of generic types, recurse inside
         if args:
             # For Callable, put the arguments into a nested list to separate
             # them from the return type
             if name == 'typing.Callable':
                 assert len(args) >= 1
-                return '{}[[{}], {}]'.format(name,
+                return '{}[[{}], {}]'.format(name_link,
                     ', '.join([extract_annotation(state, referrer_path, i) for i in args[:-1]]),
                     extract_annotation(state, referrer_path, args[-1]))
             else:
-                return '{}[{}]'.format(name, ', '.join([extract_annotation(state, referrer_path, i) for i in args]))
+                return '{}[{}]'.format(name_link, ', '.join([extract_annotation(state, referrer_path, i) for i in args]))
         else:
-            return name
+            return name_link
 
     # Things like (float, int) instead of Tuple[float, int] or using np.array
     # instead of np.ndarray. Ignore with a warning.
@@ -913,7 +917,7 @@ def extract_annotation(state: State, referrer_path: List[str], annotation) -> st
     # None and type(None) are equivalent. Calling extract_type() on None would
     # give us NoneType, which is unnecessarily long.
     elif annotation is type(None):
-        return 'None'
+        return make_name_link(state, referrer_path, '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 7629eb461e03e5affb872e03d8920deef407e852..720d2f833a4459a0a52567b5d9b71f4d24194881 100644 (file)
@@ -47,7 +47,7 @@
             </dt>
             <dd>A property</dd>
             <dt id="type_property_string_nested">
-              <a href="#type_property_string_nested" class="m-doc-self">type_property_string_nested</a>: typing.Tuple[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>, typing.List[<a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>], typing.Any] <span class="m-label m-flat m-warning">get</span>
+              <a href="#type_property_string_nested" class="m-doc-self">type_property_string_nested</a>: <a href="https://docs.python.org/3/library/typing.html#typing.Tuple" class="m-doc-external">typing.Tuple</a>[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>, <a href="https://docs.python.org/3/library/typing.html#typing.List" class="m-doc-external">typing.List</a>[<a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>], <a href="https://docs.python.org/3/library/typing.html#typing.Any" class="m-doc-external">typing.Any</a>] <span class="m-label m-flat m-warning">get</span>
             </dt>
             <dd>A property</dd>
             <dt id="type_property_writeonly">
@@ -59,7 +59,7 @@
             </dt>
             <dd>A writeonly property with invalid string type</dd>
             <dt id="type_property_writeonly_string_nested">
-              <a href="#type_property_writeonly_string_nested" class="m-doc-self">type_property_writeonly_string_nested</a>: typing.Tuple[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>, typing.List[<a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>], typing.Any] <span class="m-label m-flat m-danger">set</span>
+              <a href="#type_property_writeonly_string_nested" class="m-doc-self">type_property_writeonly_string_nested</a>: <a href="https://docs.python.org/3/library/typing.html#typing.Tuple" class="m-doc-external">typing.Tuple</a>[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>, <a href="https://docs.python.org/3/library/typing.html#typing.List" class="m-doc-external">typing.List</a>[<a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>], <a href="https://docs.python.org/3/library/typing.html#typing.Any" class="m-doc-external">typing.Any</a>] <span class="m-label m-flat m-danger">set</span>
             </dt>
             <dd>A writeonly property with a string nested type</dd>
           </dl>
index 0899d4cd15e639d4b38043dd1f0ef27d1fcc3005..21ed4833ef9c8a02d8381cf4b37e275bf292a40c 100644 (file)
@@ -42,7 +42,7 @@
             </dt>
             <dd></dd>
             <dt id="type_slot_string_nested">
-              <a href="#type_slot_string_nested" class="m-doc-self">type_slot_string_nested</a>: typing.Tuple[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>, typing.List[<a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>], typing.Any] <span class="m-label m-flat m-success">get set del</span>
+              <a href="#type_slot_string_nested" class="m-doc-self">type_slot_string_nested</a>: <a href="https://docs.python.org/3/library/typing.html#typing.Tuple" class="m-doc-external">typing.Tuple</a>[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>, <a href="https://docs.python.org/3/library/typing.html#typing.List" class="m-doc-external">typing.List</a>[<a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>], <a href="https://docs.python.org/3/library/typing.html#typing.Any" class="m-doc-external">typing.Any</a>] <span class="m-label m-flat m-success">get set del</span>
             </dt>
             <dd></dd>
           </dl>
index 0ee0df12c4073b045a40763c088caeb14ad47899..60c9e2be6cef04706573091d9842d16a91581a6d 100644 (file)
@@ -38,7 +38,7 @@
           <h2><a href="#properties">Properties</a></h2>
           <dl class="m-doc">
             <dt id="type_slot_string_invalid">
-              <a href="#type_slot_string_invalid" class="m-doc-self">type_slot_string_invalid</a>: typing.List[FooBar] <span class="m-label m-flat m-success">get set del</span>
+              <a href="#type_slot_string_invalid" class="m-doc-self">type_slot_string_invalid</a>: <a href="https://docs.python.org/3/library/typing.html#typing.List" class="m-doc-external">typing.List</a>[FooBar] <span class="m-label m-flat m-success">get set del</span>
             </dt>
             <dd></dd>
           </dl>
index 350f9bde820550c191a75d3323cc979d9b4e326a..e9933e3715dd1c39a7d97a58a33236a0742fc8fd 100644 (file)
         <section id="functions">
           <h2><a href="#functions">Functions</a></h2>
           <dl class="m-doc">
+            <dt id="returns_none">
+              <span class="m-doc-wrap-bumper">def <a href="#returns_none" class="m-doc-self">returns_none</a>(</span><span class="m-doc-wrap">a: <a href="https://docs.python.org/3/library/typing.html#typing.Callable" class="m-doc-external">typing.Callable</a>[[], <a href="https://docs.python.org/3/library/constants.html#None" class="m-doc-external">None</a>]) -&gt; <a href="https://docs.python.org/3/library/constants.html#None" class="m-doc-external">None</a></span>
+            </dt>
+            <dd>In order to disambiguate between a missing return annotation and an
+annotated none, the None return annotation is kept, converted from NoneType
+to None</dd>
+            <dt id="returns_none_type">
+              <span class="m-doc-wrap-bumper">def <a href="#returns_none_type" class="m-doc-self">returns_none_type</a>(</span><span class="m-doc-wrap">a: <a href="https://docs.python.org/3/library/typing.html#typing.Callable" class="m-doc-external">typing.Callable</a>[[], <a href="https://docs.python.org/3/library/constants.html#None" class="m-doc-external">None</a>]) -&gt; <a href="https://docs.python.org/3/library/constants.html#None" class="m-doc-external">None</a></span>
+            </dt>
+            <dd>And it should behave the same when using None or type(None)</dd>
             <dt id="type_cant_link">
               <span class="m-doc-wrap-bumper">def <a href="#type_cant_link" class="m-doc-self">type_cant_link</a>(</span><span class="m-doc-wrap">a: inspect_type_links.second._Hidden)</span>
             </dt>
             <dd>Annotation linking to a type that&#x27;s a part of INPUT_MODULES but not known</dd>
             <dt id="type_default_values">
               <span class="m-doc-wrap-bumper">def <a href="#type_default_values" class="m-doc-self">type_default_values</a>(</span><span class="m-doc-wrap">a: <a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a> = <a href="inspect_type_links.second.html#Enum-SECOND" class="m-doc">Enum.SECOND</a>,
-              b: typing.Tuple[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>] = (&lt;class &#x27;inspect_type_links.second.Foo&#x27;&gt;,),
+              b: <a href="https://docs.python.org/3/library/typing.html#typing.Tuple" class="m-doc-external">typing.Tuple</a>[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>] = (&lt;class &#x27;inspect_type_links.second.Foo&#x27;&gt;,),
               c: <a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a> = …)</span>
             </dt>
             <dd>A function with default values, one enum, one tuple and the third nonrepresentable (yes, the tuple looks ugly)</dd>
             </dt>
             <dd>Function referencing an enum</dd>
             <dt id="type_nested">
-              <span class="m-doc-wrap-bumper">def <a href="#type_nested" class="m-doc-self">type_nested</a>(</span><span class="m-doc-wrap">a: typing.Tuple[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>, typing.List[<a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>], typing.Any])</span>
+              <span class="m-doc-wrap-bumper">def <a href="#type_nested" class="m-doc-self">type_nested</a>(</span><span class="m-doc-wrap">a: <a href="https://docs.python.org/3/library/typing.html#typing.Tuple" class="m-doc-external">typing.Tuple</a>[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>, <a href="https://docs.python.org/3/library/typing.html#typing.List" class="m-doc-external">typing.List</a>[<a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>], <a href="https://docs.python.org/3/library/typing.html#typing.Any" class="m-doc-external">typing.Any</a>])</span>
             </dt>
             <dd>A function with nested type annotation</dd>
             <dt id="type_nested_string">
-              <span class="m-doc-wrap-bumper">def <a href="#type_nested_string" class="m-doc-self">type_nested_string</a>(</span><span class="m-doc-wrap">a: typing.Tuple[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>, typing.List[<a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>], typing.Any])</span>
+              <span class="m-doc-wrap-bumper">def <a href="#type_nested_string" class="m-doc-self">type_nested_string</a>(</span><span class="m-doc-wrap">a: <a href="https://docs.python.org/3/library/typing.html#typing.Tuple" class="m-doc-external">typing.Tuple</a>[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>, <a href="https://docs.python.org/3/library/typing.html#typing.List" class="m-doc-external">typing.List</a>[<a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>], <a href="https://docs.python.org/3/library/typing.html#typing.Any" class="m-doc-external">typing.Any</a>])</span>
             </dt>
             <dd>A function with nested string type annotation</dd>
             <dt id="type_nested_string_invalid">
-              <span class="m-doc-wrap-bumper">def <a href="#type_nested_string_invalid" class="m-doc-self">type_nested_string_invalid</a>(</span><span class="m-doc-wrap">a: typing.Tuple[FooBar, List[Enum], Any])</span>
+              <span class="m-doc-wrap-bumper">def <a href="#type_nested_string_invalid" class="m-doc-self">type_nested_string_invalid</a>(</span><span class="m-doc-wrap">a: <a href="https://docs.python.org/3/library/typing.html#typing.Tuple" class="m-doc-external">typing.Tuple</a>[FooBar, List[Enum], Any])</span>
             </dt>
             <dd>A function with invalid nested string type annotation</dd>
             <dt id="type_return">
             </dt>
             <dd>A function with invalid return string type annotation</dd>
             <dt id="type_return_string_nested">
-              <span class="m-doc-wrap-bumper">def <a href="#type_return_string_nested" class="m-doc-self">type_return_string_nested</a>(</span><span class="m-doc-wrap">) -&gt; typing.Tuple[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>, typing.List[<a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>], typing.Any]</span>
+              <span class="m-doc-wrap-bumper">def <a href="#type_return_string_nested" class="m-doc-self">type_return_string_nested</a>(</span><span class="m-doc-wrap">) -&gt; <a href="https://docs.python.org/3/library/typing.html#typing.Tuple" class="m-doc-external">typing.Tuple</a>[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>, <a href="https://docs.python.org/3/library/typing.html#typing.List" class="m-doc-external">typing.List</a>[<a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>], <a href="https://docs.python.org/3/library/typing.html#typing.Any" class="m-doc-external">typing.Any</a>]</span>
             </dt>
             <dd>A function with a string nested return type</dd>
             <dt id="type_string">
             </dt>
             <dd>A function with invalid string type annotation</dd>
             <dt id="type_string_nested">
-              <span class="m-doc-wrap-bumper">def <a href="#type_string_nested" class="m-doc-self">type_string_nested</a>(</span><span class="m-doc-wrap">a: typing.Tuple[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>, typing.List[<a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>], typing.Any])</span>
+              <span class="m-doc-wrap-bumper">def <a href="#type_string_nested" class="m-doc-self">type_string_nested</a>(</span><span class="m-doc-wrap">a: <a href="https://docs.python.org/3/library/typing.html#typing.Tuple" class="m-doc-external">typing.Tuple</a>[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>, <a href="https://docs.python.org/3/library/typing.html#typing.List" class="m-doc-external">typing.List</a>[<a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>], <a href="https://docs.python.org/3/library/typing.html#typing.Any" class="m-doc-external">typing.Any</a>])</span>
             </dt>
             <dd>A function with string nested type annotation</dd>
           </dl>
             </dt>
             <dd></dd>
             <dt id="TYPE_DATA_STRING_NESTED">
-              <a href="#TYPE_DATA_STRING_NESTED" class="m-doc-self">TYPE_DATA_STRING_NESTED</a>: typing.Tuple[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>, typing.List[<a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>], typing.Any] = {}
+              <a href="#TYPE_DATA_STRING_NESTED" class="m-doc-self">TYPE_DATA_STRING_NESTED</a>: <a href="https://docs.python.org/3/library/typing.html#typing.Tuple" class="m-doc-external">typing.Tuple</a>[<a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>, <a href="https://docs.python.org/3/library/typing.html#typing.List" class="m-doc-external">typing.List</a>[<a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>], <a href="https://docs.python.org/3/library/typing.html#typing.Any" class="m-doc-external">typing.Any</a>] = {}
             </dt>
             <dd></dd>
           </dl>
index e4f00baf84a330389694fb0c32ce3a1279279d20..363d2b39a714682ebd97ee8cbd4eeafe86ceb2dc 100644 (file)
@@ -1,6 +1,6 @@
 """Second module"""
 
-from typing import Tuple, List, Any
+from typing import Tuple, List, Any, Callable
 
 import enum
 
@@ -95,6 +95,14 @@ def type_cant_link(a: _Hidden):
 def type_default_values(a: Enum = Enum.SECOND, b: Tuple[Foo] = (Foo, ), c: Foo = Foo()):
     """A function with default values, one enum, one tuple and the third nonrepresentable (yes, the tuple looks ugly)"""
 
+def returns_none(a: Callable[[], None]) -> None:
+    """In order to disambiguate between a missing return annotation and an
+    annotated none, the None return annotation is kept, converted from NoneType
+    to None"""
+
+def returns_none_type(a: Callable[[], type(None)]) -> type(None):
+    """And it should behave the same when using None or type(None)"""
+
 TYPE_DATA: Foo = Foo()
 
 TYPE_DATA_STRING_NESTED: 'Tuple[Foo, List[Enum], Any]' = {}
index a8064058821b766cd660f64e45117337f88f61b7..e08ebe78f6a96da003a6fdefc001c4c0525d128d 100644 (file)
@@ -41,7 +41,7 @@
           <dl class="m-doc">
             <dt id="__init__-8f54a">
               <span class="m-doc-wrap-bumper">def <a href="#__init__-8f54a" class="m-doc-self">__init__</a>(</span><span class="m-doc-wrap">self,
-              arg0: <a href="pybind_type_links.html#Enum" class="m-doc">Enum</a><span class="m-text m-dim">, /</span>) -&gt; None</span>
+              arg0: <a href="pybind_type_links.html#Enum" class="m-doc">Enum</a><span class="m-text m-dim">, /</span>) -&gt; <a href="https://docs.python.org/3/library/constants.html#None" class="m-doc-external">None</a></span>
             </dt>
             <dd>Constructor</dd>
           </dl>
index 03428c305a73105954a6f5dbb4d66387b1f0bc1c..c65bdb31f15ff014e8cbee3f4b09d11d4c9f0bbb 100644 (file)
           <h2><a href="#functions">Functions</a></h2>
           <dl class="m-doc">
             <dt id="type_enum-3b87d">
-              <span class="m-doc-wrap-bumper">def <a href="#type_enum-3b87d" class="m-doc-self">type_enum</a>(</span><span class="m-doc-wrap">value: <a href="pybind_type_links.html#Enum" class="m-doc">Enum</a> = <a href="pybind_type_links.html#Enum-SECOND" class="m-doc">Enum.SECOND</a>) -&gt; None</span>
+              <span class="m-doc-wrap-bumper">def <a href="#type_enum-3b87d" class="m-doc-self">type_enum</a>(</span><span class="m-doc-wrap">value: <a href="pybind_type_links.html#Enum" class="m-doc">Enum</a> = <a href="pybind_type_links.html#Enum-SECOND" class="m-doc">Enum.SECOND</a>) -&gt; <a href="https://docs.python.org/3/library/constants.html#None" class="m-doc-external">None</a></span>
             </dt>
             <dd>A function taking an enum</dd>
             <dt id="type_nested-0e174">
-              <span class="m-doc-wrap-bumper">def <a href="#type_nested-0e174" class="m-doc-self">type_nested</a>(</span><span class="m-doc-wrap">arg0: typing.Tuple[<a href="pybind_type_links.Foo.html" class="m-doc">Foo</a>, typing.List[<a href="pybind_type_links.html#Enum" class="m-doc">Enum</a>]]<span class="m-text m-dim">, /</span>) -&gt; None</span>
+              <span class="m-doc-wrap-bumper">def <a href="#type_nested-0e174" class="m-doc-self">type_nested</a>(</span><span class="m-doc-wrap">arg0: <a href="https://docs.python.org/3/library/typing.html#typing.Tuple" class="m-doc-external">typing.Tuple</a>[<a href="pybind_type_links.Foo.html" class="m-doc">Foo</a>, <a href="https://docs.python.org/3/library/typing.html#typing.List" class="m-doc-external">typing.List</a>[<a href="pybind_type_links.html#Enum" class="m-doc">Enum</a>]]<span class="m-text m-dim">, /</span>) -&gt; <a href="https://docs.python.org/3/library/constants.html#None" class="m-doc-external">None</a></span>
             </dt>
             <dd>A function with nested type annotation</dd>
             <dt id="type_return-da39a">
index 0d40947f2ebb5c176521df16007295f4fe166da5..22c52101bfdb7cac46269dbc7a64010e4290279b 100644 (file)
@@ -268,8 +268,11 @@ class TypeLinks(BaseInspectTestCase):
         pybind_type_links.Foo.__annotations__ = {}
         pybind_type_links.Foo.__annotations__['TYPE_DATA'] = pybind_type_links.Enum
         self.run_python({
+            'PLUGINS': ['m.sphinx'],
             'INPUT_MODULES': [pybind_type_links],
-            'PYBIND11_COMPATIBILITY': True
+            'PYBIND11_COMPATIBILITY': True,
+            'M_SPHINX_INVENTORIES': [
+                ('../../../doc/documentation/python.inv', 'https://docs.python.org/3/', [], ['m-doc-external'])]
         })
         self.assertEqual(*self.actual_expected_contents('pybind_type_links.html'))
         self.assertEqual(*self.actual_expected_contents('pybind_type_links.Foo.html'))