return submodules_to_crawl
+def make_type_link(state: State, referrer_path: List[str], type) -> str:
+ if type is None: return None
+ assert isinstance(type, str)
+
+ # Not found, return as-is
+ if not type in state.name_map: return type
+
+ entry = state.name_map[type]
+
+ # Strip common prefix from both paths. We always want to keep at least one
+ # element from the entry path, so strip the last element off.
+ common_prefix_length = len(os.path.commonprefix([referrer_path, entry.path[:-1]]))
+
+ # Check for ambiguity of the shortened path -- for example, with referrer
+ # being `module.sub.Foo`, target `module.Foo`, the path will get shortened
+ # to `Foo`, making it seem like the target is `module.sub.Foo` instead of
+ # `module.Foo`. To fix that, the shortened path needs to be `sub.Foo`
+ # instead of `Foo`.
+ def is_ambiguous(shortened_path):
+ # Concatenate the shortened path with a prefix of the referrer path,
+ # going from longest to shortest, until we find a name that exists. If
+ # the first found name is the actual target, it's not ambiguous --
+ # for example, linking from `module.sub` to `module.sub.Foo` can be
+ # done just with `Foo` even though `module.Foo` exists as well, as it's
+ # "closer" to the referrer.
+ # TODO: See test cases in `inspect_type_links.first.Foo` for very
+ # *very* pathological cases where we're referencing `Foo` from
+ # `module.Foo` and there's also `module.Foo.Foo`. Not sure which way is
+ # better.
+ for i in reversed(range(len(referrer_path))):
+ potentially_ambiguous = referrer_path[:i] + shortened_path
+ if '.'.join(potentially_ambiguous) in state.name_map:
+ if potentially_ambiguous == entry.path: return False
+ else: return True
+ # the target *has to be* found
+ assert False # pragma: no cover
+ shortened_path = entry.path[common_prefix_length:]
+ while common_prefix_length and is_ambiguous(shortened_path):
+ common_prefix_length -= 1
+ shortened_path = entry.path[common_prefix_length:]
+
+ # Format the URL
+ if entry.type == EntryType.CLASS:
+ url = state.config['URL_FORMATTER'](entry.type, entry.path)[1]
+ else:
+ assert entry.type == EntryType.ENUM
+ parent_entry = state.name_map['.'.join(entry.path[:-1])]
+ url = '{}#{}'.format(
+ state.config['URL_FORMATTER'](parent_entry.type, parent_entry.path)[1],
+ state.config['ID_FORMATTER'](entry.type, entry.path[-1:]))
+
+ return '<a href="{}" class="m-doc">{}</a>'.format(url, '.'.join(shortened_path))
+
_pybind_name_rx = re.compile('[a-zA-Z0-9_]*')
_pybind_arg_name_rx = re.compile('[*a-zA-Z0-9_]+')
_pybind_type_rx = re.compile('[a-zA-Z0-9_.]+')
_pybind_default_value_rx = re.compile('[^,)]+')
-def parse_pybind_type(state: State, signature: str) -> str:
+def parse_pybind_type(state: State, referrer_path: List[str], signature: str) -> str:
input_type = _pybind_type_rx.match(signature).group(0)
signature = signature[len(input_type):]
type = map_name_prefix(state, input_type)
+ type_link = make_type_link(state, referrer_path, type)
if signature and signature[0] == '[':
type += '['
+ type_link += '['
signature = signature[1:]
while signature[0] != ']':
- signature, inner_type = parse_pybind_type(state, signature)
+ signature, inner_type, inner_type_link = parse_pybind_type(state, referrer_path, signature)
type += inner_type
+ type_link += inner_type_link
if signature[0] == ']': break
assert signature.startswith(', ')
signature = signature[2:]
type += ', '
+ type_link += ', '
assert signature[0] == ']'
signature = signature[1:]
type += ']'
+ type_link += ']'
- return signature, type
+ return signature, type, type_link
-def parse_pybind_signature(state: State, signature: str) -> Tuple[str, str, List[Tuple[str, str, str]], str]:
+# Returns function name, summary, list of arguments (name, type, type with HTML
+# links, default value) and return type. If argument parsing failed, the
+# argument list is a single "ellipsis" item.
+def parse_pybind_signature(state: State, referrer_path: List[str], signature: str) -> Tuple[str, str, List[Tuple[str, str, str, str]], str]:
original_signature = signature # For error reporting
name = _pybind_name_rx.match(signature).group(0)
signature = signature[len(name):]
# Type (optional)
if signature.startswith(': '):
signature = signature[2:]
- signature, arg_type = parse_pybind_type(state, signature)
+ signature, arg_type, arg_type_link = parse_pybind_type(state, referrer_path, signature)
else:
arg_type = None
+ arg_type_link = None
# Default (optional) -- for now take everything until the next comma
# TODO: ugh, do properly
else:
default = None
- args += [(arg_name, arg_type, default)]
+ args += [(arg_name, arg_type, arg_type_link, default)]
if signature[0] == ')': break
summary = extract_summary(state, {}, [], original_signature[end + 1:])
else:
summary = ''
- return (name, summary, [('…', None, None)], None)
+ return (name, summary, [('…', None, None, None)], None)
signature = signature[2:]
# Return type (optional)
if signature.startswith(' -> '):
signature = signature[4:]
- signature, return_type = parse_pybind_type(state, signature)
+ signature, _, return_type_link = parse_pybind_type(state, referrer_path, signature)
else:
- return_type = None
+ return_type_link = None
if signature and signature[0] != '\n':
end = original_signature.find('\n')
summary = extract_summary(state, {}, [], original_signature[end + 1:])
else:
summary = ''
- return (name, summary, [('…', None, None)], None)
+ return (name, summary, [('…', None, None, None)], None)
if len(signature) > 1 and signature[1] == '\n':
summary = extract_summary(state, {}, [], signature[2:])
else:
summary = ''
- return (name, summary, args, return_type)
+ return (name, summary, args, return_type_link)
+
+def parse_pybind_docstring(state: State, referrer_path: List[str], doc: str) -> List[Tuple[str, str, List[Tuple[str, str, str]], str]]:
+ name = referrer_path[-1]
-def parse_pybind_docstring(state: State, name: str, doc: str) -> List[Tuple[str, str, List[Tuple[str, str, str]], str]]:
# Multiple overloads, parse each separately
overload_header = "{}(*args, **kwargs)\nOverloaded function.\n\n".format(name);
if doc.startswith(overload_header):
next = doc.find('{}. {}('.format(id, name))
# Parse the signature and docs from known slice
- overloads += [parse_pybind_signature(state, doc[len(str(id - 1)) + 2:next])]
+ overloads += [parse_pybind_signature(state, referrer_path, doc[len(str(id - 1)) + 2:next])]
assert overloads[-1][0] == name
if next == -1: break
# Normal function, parse and return the first signature
else:
- return [parse_pybind_signature(state, doc)]
+ return [parse_pybind_signature(state, referrer_path, doc)]
def extract_summary(state: State, external_docs, path: List[str], doc: str) -> str:
# Prefer external docs, if available
# builtins (i.e., we want re.Match but not builtins.int).
return (type.__module__ + '.' if type.__module__ != 'builtins' else '') + type.__name__
-def extract_annotation(state: State, annotation) -> str:
+def extract_annotation(state: State, referrer_path: List[str], annotation) -> str:
# TODO: why this is not None directly?
if annotation is inspect.Signature.empty: return None
# Annotations can be strings, also https://stackoverflow.com/a/33533514
- if type(annotation) == str: return map_name_prefix(state, annotation)
+ if type(annotation) == str: out = annotation
# To avoid getting <class 'foo.bar'> for types (and getting foo.bar
# instead) but getting the actual type for types annotated with e.g.
# typing module or it's directly a type. In Python 3.7 this worked with
# inspect.isclass(annotation), but on 3.6 that gives True for annotations
# as well and then we would get just List instead of List[int].
- if annotation.__module__ == 'typing': return map_name_prefix(state, str(annotation))
- return map_name_prefix(state, extract_type(annotation))
+ elif annotation.__module__ == 'typing': out = str(annotation)
+ else: out = extract_type(annotation)
+
+ # Map name prefix, add links to the result
+ return make_type_link(state, referrer_path, map_name_prefix(state, out))
def extract_module_doc(state: State, path: List[str], module):
assert inspect.ismodule(module)
out.summary = extract_summary(state, {}, [], enum_.__doc__)
out.base = extract_type(enum_.__base__)
+ if out.base: out.base = make_type_link(state, path, out.base)
for i in enum_:
value = Empty()
# one function in Python may equal more than one function on the C++ side.
# To make the docs usable, list all overloads separately.
if state.config['PYBIND11_COMPATIBILITY'] and function.__doc__.startswith(path[-1]):
- funcs = parse_pybind_docstring(state, path[-1], function.__doc__)
+ funcs = parse_pybind_docstring(state, path, function.__doc__)
overloads = []
for name, summary, args, type in funcs:
out = Empty()
# Don't show None return type for void functions
out.type = None if type == 'None' else type
+ if out.type: out.type = make_type_link(state, path, out.type)
# There's no other way to check staticmethods than to check for
# self being the name of first parameter :( No support for
positional_only = True
for i, arg in enumerate(args[1:]):
- name, type, default = arg
+ name, type, type_link, default = arg
if name != 'arg{}'.format(i):
positional_only = False
break
else:
positional_only = True
for i, arg in enumerate(args):
- name, type, default = arg
+ name, type, type_link, default = arg
if name != 'arg{}'.format(i):
positional_only = False
break
+ arg_types = []
for i, arg in enumerate(args):
- name, type, default = arg
+ name, type, type_link, default = arg
param = Empty()
param.name = name
# Don't include redundant type for the self argument
- if name == 'self': param.type = None
- else: param.type = type
+ if name == 'self':
+ param.type = None
+ arg_types += [None]
+ else:
+ param.type = type_link
+ arg_types += [type]
param.default = html.escape(default or '')
if type or default: out.has_complex_params = True
# Format the anchor. Pybind11 functions are sometimes overloaded,
# thus name alone is not enough.
- out.id = state.config['ID_FORMATTER'](EntryType.OVERLOADED_FUNCTION, path[-1:] + [param.type for param in out.params])
+ out.id = state.config['ID_FORMATTER'](EntryType.OVERLOADED_FUNCTION, path[-1:] + arg_types)
overloads += [out]
try:
signature = inspect.signature(function)
- out.type = extract_annotation(state, signature.return_annotation)
+ out.type = extract_annotation(state, path, signature.return_annotation)
for i in signature.parameters.values():
param = Empty()
param.name = i.name
- param.type = extract_annotation(state, i.annotation)
+ param.type = extract_annotation(state, path, i.annotation)
if param.type:
out.has_complex_params = True
if i.default is inspect.Signature.empty:
try:
signature = inspect.signature(property.fget)
- out.type = extract_annotation(state, signature.return_annotation)
+ out.type = extract_annotation(state, path, signature.return_annotation)
except ValueError:
# pybind11 properties have the type in the docstring
if state.config['PYBIND11_COMPATIBILITY']:
- out.type = parse_pybind_signature(state, property.fget.__doc__)[3]
+ out.type = parse_pybind_signature(state, path, property.fget.__doc__)[3]
else:
out.type = None
out.summary = ''
out.has_details = False
if hasattr(parent, '__annotations__') and out.name in parent.__annotations__:
- out.type = extract_annotation(state, parent.__annotations__[out.name])
+ out.type = extract_annotation(state, path, parent.__annotations__[out.name])
else:
out.type = None
# The autogenerated <foo.bar at 0xbadbeef> is useless, so provide the value
find_package(pybind11 CONFIG REQUIRED)
-foreach(target signatures enums submodules)
+foreach(target signatures enums submodules type_links)
pybind11_add_module(pybind_${target} pybind_${target}/pybind_${target}.cpp)
set_target_properties(pybind_${target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/pybind_${target})
endforeach()
<h2><a href="#methods">Methods</a></h2>
<dl class="m-doc">
<dt>
- <span class="m-doc-wrap-bumper">def <a href="#string_annotation" class="m-doc-self" id="string_annotation">string_annotation</a>(</span><span class="m-doc-wrap">self: inspect_annotations.Foo)</span>
+ <span class="m-doc-wrap-bumper">def <a href="#string_annotation" class="m-doc-self" id="string_annotation">string_annotation</a>(</span><span class="m-doc-wrap">self: <a href="inspect_annotations.Foo.html" class="m-doc">Foo</a>)</span>
</dt>
<dd>String annotations</dd>
</dl>
<dt>
<span class="m-doc-wrap-bumper">def <a href="#annotation" class="m-doc-self" id="annotation">annotation</a>(</span><span class="m-doc-wrap">param: typing.List[int],
another: bool,
- third: str = 'hello') -> inspect_annotations.Foo</span>
+ third: str = 'hello') -> <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="#partial_annotation" class="m-doc-self" id="partial_annotation">partial_annotation</a>(</span><span class="m-doc-wrap">foo,
param: typing.Tuple[int, int],
unannotated,
- cls: inspect_annotations.Foo)</span>
+ cls: <a href="inspect_annotations.Foo.html" class="m-doc">Foo</a>)</span>
</dt>
<dd>Partially annotated function</dd>
<dt>
<h2><a href="#methods">Methods</a></h2>
<dl class="m-doc">
<dt>
- <span class="m-doc-wrap-bumper">def <a href="#a_thing" class="m-doc-self" id="a_thing">a_thing</a>(</span><span class="m-doc-wrap">self) -> inspect_name_mapping.Class</span>
+ <span class="m-doc-wrap-bumper">def <a href="#a_thing" class="m-doc-self" id="a_thing">a_thing</a>(</span><span class="m-doc-wrap">self) -> <a href="inspect_name_mapping.Class.html" class="m-doc">Class</a></span>
</dt>
<dd>A method</dd>
</dl>
<h2><a href="#functions">Functions</a></h2>
<dl class="m-doc">
<dt>
- <span class="m-doc-wrap-bumper">def <a href="#foo" class="m-doc-self" id="foo">foo</a>(</span><span class="m-doc-wrap">) -> inspect_name_mapping.Class</span>
+ <span class="m-doc-wrap-bumper">def <a href="#foo" class="m-doc-self" id="foo">foo</a>(</span><span class="m-doc-wrap">) -> <a href="inspect_name_mapping.Class.html" class="m-doc">Class</a></span>
</dt>
<dd>This function returns Class, *not* _sub.Foo</dd>
</dl>
<h2><a href="#functions">Functions</a></h2>
<dl class="m-doc">
<dt>
- <span class="m-doc-wrap-bumper">def <a href="#foo" class="m-doc-self" id="foo">foo</a>(</span><span class="m-doc-wrap">a: inspect_name_mapping.Class,
+ <span class="m-doc-wrap-bumper">def <a href="#foo" class="m-doc-self" id="foo">foo</a>(</span><span class="m-doc-wrap">a: <a href="inspect_name_mapping.Class.html" class="m-doc">Class</a>,
b: int) -> int</span>
</dt>
<dd>A function</dd>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>inspect_type_links.first.Foo.Foo | My Python Project</title>
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
+ <link rel="stylesheet" href="m-dark+documentation.compiled.css" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+ <div class="m-container">
+ <div class="m-row">
+ <a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">My Python Project</a>
+ </div>
+ </div>
+</nav></header>
+<main><article>
+ <div class="m-container m-container-inflatable">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <h1>
+ <span class="m-breadcrumb"><a href="inspect_type_links.html">inspect_type_links</a>.<wbr/></span><span class="m-breadcrumb"><a href="inspect_type_links.first.html">first</a>.<wbr/></span><span class="m-breadcrumb"><a href="inspect_type_links.first.Foo.html">Foo</a>.<wbr/></span>Foo <span class="m-thin">class</span>
+ </h1>
+ <p>An inner class in the first module</p>
+ <div class="m-block m-default">
+ <h3>Contents</h3>
+ <ul>
+ <li>
+ Reference
+ <ul>
+ <li><a href="#methods">Methods</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <section id="methods">
+ <h2><a href="#methods">Methods</a></h2>
+ <dl class="m-doc">
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#reference_parent" class="m-doc-self" id="reference_parent">reference_parent</a>(</span><span class="m-doc-wrap">self,
+ a: <a href="inspect_type_links.first.Foo.html" class="m-doc">first.Foo</a>)</span>
+ </dt>
+ <dd>A method referencing its parent wrapper class</dd>
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#reference_self" class="m-doc-self" id="reference_self">reference_self</a>(</span><span class="m-doc-wrap">self,
+ a: <a href="inspect_type_links.first.Foo.Foo.html" class="m-doc">Foo</a>)</span>
+ </dt>
+ <dd>A method referencing its wrapper class</dd>
+ </dl>
+ </section>
+ </div>
+ </div>
+ </div>
+</article></main>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>inspect_type_links.first.Foo | My Python Project</title>
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
+ <link rel="stylesheet" href="m-dark+documentation.compiled.css" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+ <div class="m-container">
+ <div class="m-row">
+ <a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">My Python Project</a>
+ </div>
+ </div>
+</nav></header>
+<main><article>
+ <div class="m-container m-container-inflatable">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <h1>
+ <span class="m-breadcrumb"><a href="inspect_type_links.html">inspect_type_links</a>.<wbr/></span><span class="m-breadcrumb"><a href="inspect_type_links.first.html">first</a>.<wbr/></span>Foo <span class="m-thin">class</span>
+ </h1>
+ <p>A class in the first module</p>
+ <div class="m-block m-default">
+ <h3>Contents</h3>
+ <ul>
+ <li>
+ Reference
+ <ul>
+ <li><a href="#classes">Classes</a></li>
+ <li><a href="#methods">Methods</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <section id="classes">
+ <h2><a href="#classes">Classes</a></h2>
+ <dl class="m-doc">
+ <dt>class <a href="inspect_type_links.first.Foo.Foo.html" class="m-doc">Foo</a></dt>
+ <dd>An inner class in the first module</dd>
+ </dl>
+ </section>
+ <section id="methods">
+ <h2><a href="#methods">Methods</a></h2>
+ <dl class="m-doc">
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#reference_inner" class="m-doc-self" id="reference_inner">reference_inner</a>(</span><span class="m-doc-wrap">self,
+ a: <a href="inspect_type_links.first.Foo.Foo.html" class="m-doc">Foo</a>)</span>
+ </dt>
+ <dd>A method referencing an inner class. This is quite a pathological case and I'm not sure if Foo or Foo.Foo is better.</dd>
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#reference_other" class="m-doc-self" id="reference_other">reference_other</a>(</span><span class="m-doc-wrap">self,
+ a: <a href="inspect_type_links.second.Foo.html" class="m-doc">second.Foo</a>)</span>
+ </dt>
+ <dd>A method referencing a type in another module</dd>
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#reference_self" class="m-doc-self" id="reference_self">reference_self</a>(</span><span class="m-doc-wrap">self,
+ a: <a href="inspect_type_links.first.Foo.html" class="m-doc">first.Foo</a>)</span>
+ </dt>
+ <dd>A method referencing its wrapper class. Due to the inner Foo this is quite a pathological case and I'm not sure if first.Foo or Foo is better.</dd>
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#reference_sub" class="m-doc-self" id="reference_sub">reference_sub</a>(</span><span class="m-doc-wrap">self,
+ a: <a href="inspect_type_links.first.sub.Foo.html" class="m-doc">sub.Foo</a>,
+ b: <a href="inspect_type_links.first.sub.Foo.html" class="m-doc">sub.Foo</a>)</span>
+ </dt>
+ <dd>A method referencing a type in a submodule</dd>
+ </dl>
+ </section>
+ </div>
+ </div>
+ </div>
+</article></main>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>inspect_type_links.first | My Python Project</title>
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
+ <link rel="stylesheet" href="m-dark+documentation.compiled.css" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+ <div class="m-container">
+ <div class="m-row">
+ <a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">My Python Project</a>
+ </div>
+ </div>
+</nav></header>
+<main><article>
+ <div class="m-container m-container-inflatable">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <h1>
+ <span class="m-breadcrumb"><a href="inspect_type_links.html">inspect_type_links</a>.<wbr/></span>first <span class="m-thin">module</span>
+ </h1>
+ <p>First module</p>
+ <div class="m-block m-default">
+ <h3>Contents</h3>
+ <ul>
+ <li>
+ Reference
+ <ul>
+ <li><a href="#packages">Modules</a></li>
+ <li><a href="#classes">Classes</a></li>
+ <li><a href="#functions">Functions</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <section id="namespaces">
+ <h2><a href="#namespaces">Modules</a></h2>
+ <dl class="m-doc">
+ <dt>module <a href="inspect_type_links.first.sub.html" class="m-doc">sub</a></dt>
+ <dd>Submodule</dd>
+ </dl>
+ </section>
+ <section id="classes">
+ <h2><a href="#classes">Classes</a></h2>
+ <dl class="m-doc">
+ <dt>class <a href="inspect_type_links.first.Foo.html" class="m-doc">Foo</a></dt>
+ <dd>A class in the first module</dd>
+ </dl>
+ </section>
+ <section id="functions">
+ <h2><a href="#functions">Functions</a></h2>
+ <dl class="m-doc">
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#reference_other" class="m-doc-self" id="reference_other">reference_other</a>(</span><span class="m-doc-wrap">a: <a href="inspect_type_links.second.Foo.html" class="m-doc">second.Foo</a>)</span>
+ </dt>
+ <dd>A function referencing a type in another module</dd>
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#reference_self" class="m-doc-self" id="reference_self">reference_self</a>(</span><span class="m-doc-wrap">a: <a href="inspect_type_links.first.Foo.html" class="m-doc">Foo</a>,
+ b: <a href="inspect_type_links.first.Foo.html" class="m-doc">Foo</a>)</span>
+ </dt>
+ <dd>A function referencing a type in this module</dd>
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#reference_sub" class="m-doc-self" id="reference_sub">reference_sub</a>(</span><span class="m-doc-wrap">a: <a href="inspect_type_links.first.sub.Foo.html" class="m-doc">sub.Foo</a>,
+ b: <a href="inspect_type_links.first.sub.Foo.html" class="m-doc">sub.Foo</a>)</span>
+ </dt>
+ <dd>A function referencing a type in a submodule</dd>
+ </dl>
+ </section>
+ </div>
+ </div>
+ </div>
+</article></main>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>inspect_type_links.first.sub.Foo | My Python Project</title>
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
+ <link rel="stylesheet" href="m-dark+documentation.compiled.css" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+ <div class="m-container">
+ <div class="m-row">
+ <a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">My Python Project</a>
+ </div>
+ </div>
+</nav></header>
+<main><article>
+ <div class="m-container m-container-inflatable">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <h1>
+ <span class="m-breadcrumb"><a href="inspect_type_links.html">inspect_type_links</a>.<wbr/></span><span class="m-breadcrumb"><a href="inspect_type_links.first.html">first</a>.<wbr/></span><span class="m-breadcrumb"><a href="inspect_type_links.first.sub.html">sub</a>.<wbr/></span>Foo <span class="m-thin">class</span>
+ </h1>
+ <p>A class in the submodule</p>
+ <div class="m-block m-default">
+ <h3>Contents</h3>
+ <ul>
+ <li>
+ Reference
+ <ul>
+ <li><a href="#methods">Methods</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <section id="methods">
+ <h2><a href="#methods">Methods</a></h2>
+ <dl class="m-doc">
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#reference_parent" class="m-doc-self" id="reference_parent">reference_parent</a>(</span><span class="m-doc-wrap">a: <a href="inspect_type_links.first.Foo.html" class="m-doc">first.Foo</a>,
+ b: <a href="inspect_type_links.first.Foo.html" class="m-doc">first.Foo</a>)</span>
+ </dt>
+ <dd>A method referencing a type in a parent module</dd>
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#reference_self" class="m-doc-self" id="reference_self">reference_self</a>(</span><span class="m-doc-wrap">a: <a href="inspect_type_links.first.sub.Foo.html" class="m-doc">Foo</a>)</span>
+ </dt>
+ <dd>A method referencing a type in this submodule</dd>
+ </dl>
+ </section>
+ </div>
+ </div>
+ </div>
+</article></main>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>inspect_type_links.first.sub | My Python Project</title>
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
+ <link rel="stylesheet" href="m-dark+documentation.compiled.css" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+ <div class="m-container">
+ <div class="m-row">
+ <a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">My Python Project</a>
+ </div>
+ </div>
+</nav></header>
+<main><article>
+ <div class="m-container m-container-inflatable">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <h1>
+ <span class="m-breadcrumb"><a href="inspect_type_links.html">inspect_type_links</a>.<wbr/></span><span class="m-breadcrumb"><a href="inspect_type_links.first.html">first</a>.<wbr/></span>sub <span class="m-thin">module</span>
+ </h1>
+ <p>Submodule</p>
+ <div class="m-block m-default">
+ <h3>Contents</h3>
+ <ul>
+ <li>
+ Reference
+ <ul>
+ <li><a href="#classes">Classes</a></li>
+ <li><a href="#functions">Functions</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <section id="classes">
+ <h2><a href="#classes">Classes</a></h2>
+ <dl class="m-doc">
+ <dt>class <a href="inspect_type_links.first.sub.Foo.html" class="m-doc">Foo</a></dt>
+ <dd>A class in the submodule</dd>
+ </dl>
+ </section>
+ <section id="functions">
+ <h2><a href="#functions">Functions</a></h2>
+ <dl class="m-doc">
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#reference_parent" class="m-doc-self" id="reference_parent">reference_parent</a>(</span><span class="m-doc-wrap">a: <a href="inspect_type_links.first.Foo.html" class="m-doc">first.Foo</a>,
+ b: <a href="inspect_type_links.first.Foo.html" class="m-doc">first.Foo</a>)</span>
+ </dt>
+ <dd>A function referencing a type in a parent module</dd>
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#reference_self" class="m-doc-self" id="reference_self">reference_self</a>(</span><span class="m-doc-wrap">a: <a href="inspect_type_links.first.sub.Foo.html" class="m-doc">Foo</a>,
+ b: <a href="inspect_type_links.first.sub.Foo.html" class="m-doc">Foo</a>)</span>
+ </dt>
+ <dd>A function referencing a type in this submodule</dd>
+ </dl>
+ </section>
+ </div>
+ </div>
+ </div>
+</article></main>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>inspect_type_links.second.Foo | My Python Project</title>
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
+ <link rel="stylesheet" href="m-dark+documentation.compiled.css" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+ <div class="m-container">
+ <div class="m-row">
+ <a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">My Python Project</a>
+ </div>
+ </div>
+</nav></header>
+<main><article>
+ <div class="m-container m-container-inflatable">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <h1>
+ <span class="m-breadcrumb"><a href="inspect_type_links.html">inspect_type_links</a>.<wbr/></span><span class="m-breadcrumb"><a href="inspect_type_links.second.html">second</a>.<wbr/></span>Foo <span class="m-thin">class</span>
+ </h1>
+ <p>A class in the second module</p>
+ <div class="m-block m-default">
+ <h3>Contents</h3>
+ <ul>
+ <li>
+ Reference
+ <ul>
+ <li><a href="#properties">Properties</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <section id="properties">
+ <h2><a href="#properties">Properties</a></h2>
+ <dl class="m-doc">
+ <dt>
+ <a href="#type_property" class="m-doc-self" id="type_property">type_property</a>: <a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a> <span class="m-label m-flat m-warning">get</span>
+ </dt>
+ <dd>A property</dd>
+ </dl>
+ </section>
+ </div>
+ </div>
+ </div>
+</article></main>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>inspect_type_links.second | My Python Project</title>
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
+ <link rel="stylesheet" href="m-dark+documentation.compiled.css" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+ <div class="m-container">
+ <div class="m-row">
+ <a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">My Python Project</a>
+ </div>
+ </div>
+</nav></header>
+<main><article>
+ <div class="m-container m-container-inflatable">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <h1>
+ <span class="m-breadcrumb"><a href="inspect_type_links.html">inspect_type_links</a>.<wbr/></span>second <span class="m-thin">module</span>
+ </h1>
+ <p>Second module</p>
+ <div class="m-block m-default">
+ <h3>Contents</h3>
+ <ul>
+ <li>
+ Reference
+ <ul>
+ <li><a href="#classes">Classes</a></li>
+ <li><a href="#enums">Enums</a></li>
+ <li><a href="#functions">Functions</a></li>
+ <li><a href="#data">Data</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <section id="classes">
+ <h2><a href="#classes">Classes</a></h2>
+ <dl class="m-doc">
+ <dt>class <a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a></dt>
+ <dd>A class in the second module</dd>
+ </dl>
+ </section>
+ <section id="enums">
+ <h2><a href="#enums">Enums</a></h2>
+ <dl class="m-doc">
+ <dt>
+ <span class="m-doc-wrap-bumper">class <a href="#Enum" class="m-doc-self" id="Enum">Enum</a>(enum.Enum): </span><span class="m-doc-wrap"><a href="#Enum-FIRST" class="m-doc-self" id="Enum-FIRST">FIRST</a> = 1
+ <a href="#Enum-SECOND" class="m-doc-self" id="Enum-SECOND">SECOND</a> = 2</span>
+ </dt>
+ <dd>An enum</dd>
+ </dl>
+ </section>
+ <section id="functions">
+ <h2><a href="#functions">Functions</a></h2>
+ <dl class="m-doc">
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#type_enum" class="m-doc-self" id="type_enum">type_enum</a>(</span><span class="m-doc-wrap">a: <a href="inspect_type_links.second.html#Enum" class="m-doc">Enum</a>)</span>
+ </dt>
+ <dd>Function referencing an enum</dd>
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#type_return" class="m-doc-self" id="type_return">type_return</a>(</span><span class="m-doc-wrap">) -> <a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a></span>
+ </dt>
+ <dd>A function with a return type annotation</dd>
+ </dl>
+ </section>
+ <section id="data">
+ <h2><a href="#data">Data</a></h2>
+ <dl class="m-doc">
+ <dt>
+ <a href="#TYPE_DATA" class="m-doc-self" id="TYPE_DATA">TYPE_DATA</a>: <a href="inspect_type_links.second.Foo.html" class="m-doc">Foo</a>
+ </dt>
+ <dd></dd>
+ </dl>
+ </section>
+ </div>
+ </div>
+ </div>
+</article></main>
+</body>
+</html>
--- /dev/null
+from . import first, second
--- /dev/null
+"""First module"""
+
+from inspect_type_links import first
+from inspect_type_links import second
+
+class Foo:
+ """A class in the first module"""
+
+ def reference_self(self, a: 'inspect_type_links.first.Foo'):
+ """A method referencing its wrapper class. Due to the inner Foo this is quite a pathological case and I'm not sure if first.Foo or Foo is better."""
+
+ def reference_inner(self, a: 'inspect_type_links.first.Foo.Foo'):
+ """A method referencing an inner class. This is quite a pathological case and I'm not sure if Foo or Foo.Foo is better."""
+
+ def reference_other(self, a: second.Foo):
+ """A method referencing a type in another module"""
+
+ class Foo:
+ """An inner class in the first module"""
+
+ def reference_self(self, a: 'inspect_type_links.first.Foo.Foo'):
+ """A method referencing its wrapper class"""
+
+ def reference_parent(self, a: 'inspect_type_links.first.Foo'):
+ """A method referencing its parent wrapper class"""
+
+def reference_self(a: Foo, b: first.Foo):
+ """A function referencing a type in this module"""
+
+def reference_other(a: second.Foo):
+ """A function referencing a type in another module"""
+
+from . import sub
+
+def _foo_reference_sub(self, a: sub.Foo, b: first.sub.Foo):
+ """A method referencing a type in a submodule"""
+
+setattr(Foo, 'reference_sub', _foo_reference_sub)
+
+def reference_sub(a: sub.Foo, b: first.sub.Foo):
+ """A function referencing a type in a submodule"""
--- /dev/null
+"""Submodule"""
+
+from inspect_type_links import first
+
+class Foo:
+ """A class in the submodule"""
+
+ def reference_self(a: 'inspect_type_links.first.sub.Foo'):
+ """A method referencing a type in this submodule"""
+
+ def reference_parent(a: first.Foo, b: first.Foo):
+ """A method referencing a type in a parent module"""
+
+def reference_self(a: Foo, b: 'inspect_type_links.first.sub.Foo'):
+ """A function referencing a type in this submodule"""
+
+def reference_parent(a: first.Foo, b: first.Foo):
+ """A function referencing a type in a parent module"""
--- /dev/null
+"""Second module"""
+
+import enum
+
+class Enum(enum.Enum):
+ """An enum"""
+
+ FIRST = 1
+ SECOND = 2
+
+def type_enum(a: Enum):
+ """Function referencing an enum"""
+
+class Foo:
+ """A class in the second module"""
+
+ @property
+ def type_property(self) -> Enum:
+ """A property"""
+
+def type_return() -> Foo:
+ """A function with a return type annotation"""
+
+TYPE_DATA: Foo = Foo()
<dd>Each overload should have a different hash</dd>
<dt>
<span class="m-doc-wrap-bumper">def <a href="#o-an_overloaded_function-d36ce" class="m-doc-self" id="o-an_overloaded_function-d36ce">an_overloaded_function</a>(</span><span class="m-doc-wrap">arg0: int,
- arg1: link_formatting.pybind.Foo<span class="m-text m-dim">, /</span>) -> int</span>
+ arg1: <a href="c.link_formatting.pybind.Foo.html#this-is-an-url" class="m-doc">Foo</a><span class="m-text m-dim">, /</span>) -> int</span>
</dt>
<dd>Each overload should have a different hash</dd>
<dt>
<h2><a href="#staticmethods">Static methods</a></h2>
<dl class="m-doc">
<dt>
- <span class="m-doc-wrap-bumper">def <a href="#a_thing-da39a" class="m-doc-self" id="a_thing-da39a">a_thing</a>(</span><span class="m-doc-wrap">) -> pybind_name_mapping.Class</span>
+ <span class="m-doc-wrap-bumper">def <a href="#a_thing-da39a" class="m-doc-self" id="a_thing-da39a">a_thing</a>(</span><span class="m-doc-wrap">) -> <a href="pybind_name_mapping.Class.html" class="m-doc">Class</a></span>
</dt>
<dd>A method</dd>
</dl>
<h2><a href="#functions">Functions</a></h2>
<dl class="m-doc">
<dt>
- <span class="m-doc-wrap-bumper">def <a href="#foo" class="m-doc-self" id="foo">foo</a>(</span><span class="m-doc-wrap">) -> pybind_name_mapping.Class</span>
+ <span class="m-doc-wrap-bumper">def <a href="#foo" class="m-doc-self" id="foo">foo</a>(</span><span class="m-doc-wrap">) -> <a href="pybind_name_mapping.Class.html" class="m-doc">Class</a></span>
</dt>
<dd>This function returns Class, *not* _sub.Foo</dd>
</dl>
<h2><a href="#functions">Functions</a></h2>
<dl class="m-doc">
<dt>
- <span class="m-doc-wrap-bumper">def <a href="#foo-c5914" class="m-doc-self" id="foo-c5914">foo</a>(</span><span class="m-doc-wrap">arg0: pybind_name_mapping.Class,
+ <span class="m-doc-wrap-bumper">def <a href="#foo-c5914" class="m-doc-self" id="foo-c5914">foo</a>(</span><span class="m-doc-wrap">arg0: <a href="pybind_name_mapping.Class.html" class="m-doc">Class</a>,
arg1: int<span class="m-text m-dim">, /</span>) -> int</span>
</dt>
<dd>A function</dd>
<dl class="m-doc">
<dt>
<span class="m-doc-wrap-bumper">def <a href="#static_function-8f19c" class="m-doc-self" id="static_function-8f19c">static_function</a>(</span><span class="m-doc-wrap">arg0: int,
- arg1: float<span class="m-text m-dim">, /</span>) -> pybind_signatures.MyClass</span>
+ arg1: float<span class="m-text m-dim">, /</span>) -> <a href="pybind_signatures.MyClass.html" class="m-doc">MyClass</a></span>
</dt>
<dd>Static method with positional-only args</dd>
</dl>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>pybind_type_links.Foo | My Python Project</title>
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
+ <link rel="stylesheet" href="m-dark+documentation.compiled.css" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+ <div class="m-container">
+ <div class="m-row">
+ <a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">My Python Project</a>
+ </div>
+ </div>
+</nav></header>
+<main><article>
+ <div class="m-container m-container-inflatable">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <h1>
+ <span class="m-breadcrumb"><a href="pybind_type_links.html">pybind_type_links</a>.<wbr/></span>Foo <span class="m-thin">class</span>
+ </h1>
+ <p>A class</p>
+ <div class="m-block m-default">
+ <h3>Contents</h3>
+ <ul>
+ <li>
+ Reference
+ <ul>
+ <li><a href="#dunder-methods">Special methods</a></li>
+ <li><a href="#properties">Properties</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <section id="dunder-methods">
+ <h2><a href="#dunder-methods">Special methods</a></h2>
+ <dl class="m-doc">
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#__init__-8f54a" class="m-doc-self" id="__init__-8f54a">__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>)</span>
+ </dt>
+ <dd>Constructor</dd>
+ </dl>
+ </section>
+ <section id="properties">
+ <h2><a href="#properties">Properties</a></h2>
+ <dl class="m-doc">
+ <dt>
+ <a href="#property" class="m-doc-self" id="property">property</a>: <a href="pybind_type_links.html#Enum" class="m-doc">Enum</a> <span class="m-label m-flat m-success">get set</span>
+ </dt>
+ <dd>A property</dd>
+ </dl>
+ </section>
+ </div>
+ </div>
+ </div>
+</article></main>
+</body>
+</html>
--- /dev/null
+#include <pybind11/pybind11.h>
+
+namespace py = pybind11;
+
+namespace {
+
+enum class Enum {
+ First, Second
+};
+
+void typeEnum(Enum) {}
+
+struct Foo {
+ Enum property;
+};
+
+Foo typeReturn() { return {}; }
+
+}
+
+PYBIND11_MODULE(pybind_type_links, m) {
+ m.doc() = "pybind11 type linking";
+
+ py::enum_<Enum>{m, "Enum", "An enum"}
+ .value("FIRST", Enum::First)
+ .value("SECOND", Enum::Second);
+
+ py::class_<Foo>{m, "Foo", "A class"}
+ .def(py::init<Enum>(), "Constructor")
+ .def_readwrite("property", &Foo::property, "A property");
+
+ m
+ .def("type_enum", &typeEnum, "A function taking an enum")
+ .def("type_return", &typeReturn, "A function returning a type");
+}
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>pybind_type_links | My Python Project</title>
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
+ <link rel="stylesheet" href="m-dark+documentation.compiled.css" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+</head>
+<body>
+<header><nav id="navigation">
+ <div class="m-container">
+ <div class="m-row">
+ <a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">My Python Project</a>
+ </div>
+ </div>
+</nav></header>
+<main><article>
+ <div class="m-container m-container-inflatable">
+ <div class="m-row">
+ <div class="m-col-l-10 m-push-l-1">
+ <h1>
+ pybind_type_links <span class="m-thin">module</span>
+ </h1>
+ <p>pybind11 type linking</p>
+ <div class="m-block m-default">
+ <h3>Contents</h3>
+ <ul>
+ <li>
+ Reference
+ <ul>
+ <li><a href="#classes">Classes</a></li>
+ <li><a href="#enums">Enums</a></li>
+ <li><a href="#functions">Functions</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <section id="classes">
+ <h2><a href="#classes">Classes</a></h2>
+ <dl class="m-doc">
+ <dt>class <a href="pybind_type_links.Foo.html" class="m-doc">Foo</a></dt>
+ <dd>A class</dd>
+ </dl>
+ </section>
+ <section id="enums">
+ <h2><a href="#enums">Enums</a></h2>
+ <dl class="m-doc">
+ <dt>
+ <span class="m-doc-wrap-bumper">class <a href="#Enum" class="m-doc-self" id="Enum">Enum</a>: </span><span class="m-doc-wrap"><a href="#Enum-FIRST" class="m-doc-self" id="Enum-FIRST">FIRST</a> = 0
+ <a href="#Enum-SECOND" class="m-doc-self" id="Enum-SECOND">SECOND</a> = 1</span>
+ </dt>
+ <dd>An enum</dd>
+ </dl>
+ </section>
+ <section id="functions">
+ <h2><a href="#functions">Functions</a></h2>
+ <dl class="m-doc">
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#type_enum-3b87d" class="m-doc-self" id="type_enum-3b87d">type_enum</a>(</span><span class="m-doc-wrap">arg0: <a href="pybind_type_links.html#Enum" class="m-doc">Enum</a><span class="m-text m-dim">, /</span>)</span>
+ </dt>
+ <dd>A function taking an enum</dd>
+ <dt>
+ <span class="m-doc-wrap-bumper">def <a href="#type_return-da39a" class="m-doc-self" id="type_return-da39a">type_return</a>(</span><span class="m-doc-wrap">) -> <a href="pybind_type_links.Foo.html" class="m-doc">Foo</a></span>
+ </dt>
+ <dd>A function returning a type</dd>
+ </dl>
+ </section>
+ </div>
+ </div>
+ </div>
+</article></main>
+</body>
+</html>
self.assertEqual(*self.actual_expected_contents('inspect_recursive.html'))
self.assertEqual(*self.actual_expected_contents('inspect_recursive.first.html'))
self.assertEqual(*self.actual_expected_contents('inspect_recursive.a.html'))
+
+class TypeLinks(BaseInspectTestCase):
+ def __init__(self, *args, **kwargs):
+ super().__init__(__file__, 'type_links', *args, **kwargs)
+
+ def test(self):
+ self.run_python()
+ self.assertEqual(*self.actual_expected_contents('inspect_type_links.first.html'))
+ self.assertEqual(*self.actual_expected_contents('inspect_type_links.first.Foo.html'))
+ self.assertEqual(*self.actual_expected_contents('inspect_type_links.first.Foo.Foo.html'))
+ self.assertEqual(*self.actual_expected_contents('inspect_type_links.first.sub.html'))
+ self.assertEqual(*self.actual_expected_contents('inspect_type_links.first.sub.Foo.html'))
+
+ self.assertEqual(*self.actual_expected_contents('inspect_type_links.second.html'))
+ self.assertEqual(*self.actual_expected_contents('inspect_type_links.second.Foo.html'))
class Signature(unittest.TestCase):
def test(self):
- self.assertEqual(parse_pybind_signature(State({}),
+ self.assertEqual(parse_pybind_signature(State({}), [],
'foo(a: int, a2: module.Thing) -> module.Thing3'),
('foo', '', [
- ('a', 'int', None),
- ('a2', 'module.Thing', None),
+ ('a', 'int', 'int', None),
+ ('a2', 'module.Thing', 'module.Thing', None),
], 'module.Thing3'))
def test_newline(self):
- self.assertEqual(parse_pybind_signature(State({}),
+ self.assertEqual(parse_pybind_signature(State({}), [],
'foo(a: int, a2: module.Thing) -> module.Thing3\n'),
('foo', '', [
- ('a', 'int', None),
- ('a2', 'module.Thing', None),
+ ('a', 'int', 'int', None),
+ ('a2', 'module.Thing', 'module.Thing', None),
], 'module.Thing3'))
def test_docs(self):
- self.assertEqual(parse_pybind_signature(State({}),
+ self.assertEqual(parse_pybind_signature(State({}), [],
'foo(a: int, a2: module.Thing) -> module.Thing3\n\nDocs here!!'),
('foo', 'Docs here!!', [
- ('a', 'int', None),
- ('a2', 'module.Thing', None),
+ ('a', 'int', 'int', None),
+ ('a2', 'module.Thing', 'module.Thing', None),
], 'module.Thing3'))
def test_no_args(self):
- self.assertEqual(parse_pybind_signature(State({}),
+ self.assertEqual(parse_pybind_signature(State({}), [],
'thingy() -> str'),
('thingy', '', [], 'str'))
def test_no_return(self):
- self.assertEqual(parse_pybind_signature(State({}),
+ self.assertEqual(parse_pybind_signature(State({}), [],
'__init__(self: module.Thing)'),
('__init__', '', [
- ('self', 'module.Thing', None),
+ ('self', 'module.Thing', 'module.Thing', None),
], None))
def test_no_arg_types(self):
- self.assertEqual(parse_pybind_signature(State({}),
+ self.assertEqual(parse_pybind_signature(State({}), [],
'thingy(self, the_other_thing)'),
('thingy', '', [
- ('self', None, None),
- ('the_other_thing', None, None),
+ ('self', None, None, None),
+ ('the_other_thing', None, None, None),
], None))
def test_square_brackets(self):
- self.assertEqual(parse_pybind_signature(State({}),
+ self.assertEqual(parse_pybind_signature(State({}), [],
'foo(a: Tuple[int, str], no_really: str) -> List[str]'),
('foo', '', [
- ('a', 'Tuple[int, str]', None),
- ('no_really', 'str', None),
+ ('a', 'Tuple[int, str]', 'Tuple[int, str]', None),
+ ('no_really', 'str', 'str', None),
], 'List[str]'))
def test_nested_square_brackets(self):
- self.assertEqual(parse_pybind_signature(State({}),
+ self.assertEqual(parse_pybind_signature(State({}), [],
'foo(a: Tuple[int, List[Tuple[int, int]]], another: float) -> Union[str, Any]'),
('foo', '', [
- ('a', 'Tuple[int, List[Tuple[int, int]]]', None),
- ('another', 'float', None),
+ ('a', 'Tuple[int, List[Tuple[int, int]]]', 'Tuple[int, List[Tuple[int, int]]]', None),
+ ('another', 'float', 'float', None),
], 'Union[str, Any]'))
def test_kwargs(self):
- self.assertEqual(parse_pybind_signature(State({}),
+ self.assertEqual(parse_pybind_signature(State({}), [],
'foo(*args, **kwargs)'),
('foo', '', [
- ('*args', None, None),
- ('**kwargs', None, None),
+ ('*args', None, None, None),
+ ('**kwargs', None, None, None),
], None))
# https://github.com/pybind/pybind11/commit/0826b3c10607c8d96e1d89dc819c33af3799a7b8,
# released in 2.3.0. We want to support both, so test both.
def test_default_values_pybind22(self):
- self.assertEqual(parse_pybind_signature(State({}),
+ self.assertEqual(parse_pybind_signature(State({}), [],
'foo(a: float=1.0, b: str=\'hello\')'),
('foo', '', [
- ('a', 'float', '1.0'),
- ('b', 'str', '\'hello\''),
+ ('a', 'float', 'float', '1.0'),
+ ('b', 'str', 'str', '\'hello\''),
], None))
def test_default_values_pybind23(self):
- self.assertEqual(parse_pybind_signature(State({}),
+ self.assertEqual(parse_pybind_signature(State({}), [],
'foo(a: float = 1.0, b: str = \'hello\')'),
('foo', '', [
- ('a', 'float', '1.0'),
- ('b', 'str', '\'hello\''),
+ ('a', 'float', 'float', '1.0'),
+ ('b', 'str', 'str', '\'hello\''),
], None))
def test_crazy_stuff(self):
- self.assertEqual(parse_pybind_signature(State({}),
+ self.assertEqual(parse_pybind_signature(State({}), [],
'foo(a: int, b: Math::Vector<4, UnsignedInt>)'),
- ('foo', '', [('…', None, None)], None))
+ ('foo', '', [('…', None, None, None)], None))
def test_crazy_stuff_docs(self):
- self.assertEqual(parse_pybind_signature(State({}),
+ self.assertEqual(parse_pybind_signature(State({}), [],
'foo(a: int, b: Math::Vector<4, UnsignedInt>)\n\nThis is text!!'),
- ('foo', 'This is text!!', [('…', None, None)], None))
+ ('foo', 'This is text!!', [('…', None, None, None)], None))
def test_crazy_return(self):
- self.assertEqual(parse_pybind_signature(State({}),
+ self.assertEqual(parse_pybind_signature(State({}), [],
'foo(a: int) -> Math::Vector<4, UnsignedInt>'),
- ('foo', '', [('…', None, None)], None))
+ ('foo', '', [('…', None, None, None)], None))
def test_crazy_return_docs(self):
- self.assertEqual(parse_pybind_signature(State({}),
+ self.assertEqual(parse_pybind_signature(State({}), [],
'foo(a: int) -> Math::Vector<4, UnsignedInt>\n\nThis returns!'),
- ('foo', 'This returns!', [('…', None, None)], None))
+ ('foo', 'This returns!', [('…', None, None, None)], None))
def test_no_name(self):
- self.assertEqual(parse_pybind_signature(State({}),
+ self.assertEqual(parse_pybind_signature(State({}), [],
'(arg0: MyClass) -> float'),
- ('', '', [('arg0', 'MyClass', None)], 'float'))
+ ('', '', [('arg0', 'MyClass', 'MyClass', None)], 'float'))
def test_module_mapping(self):
state = State({})
state.module_mapping['module._module'] = 'module'
- self.assertEqual(parse_pybind_signature(state,
+ self.assertEqual(parse_pybind_signature(state, [],
'foo(a: module._module.Foo, b: Tuple[int, module._module.Bar]) -> module._module.Baz'),
- ('foo', '', [('a', 'module.Foo', None),
- ('b', 'Tuple[int, module.Bar]', None)], 'module.Baz'))
+ ('foo', '', [('a', 'module.Foo', 'module.Foo', None),
+ ('b', 'Tuple[int, module.Bar]', 'Tuple[int, module.Bar]', None)], 'module.Baz'))
class Signatures(BaseInspectTestCase):
def __init__(self, *args, **kwargs):
self.assertEqual(*self.actual_expected_contents('pybind_name_mapping.html'))
self.assertEqual(*self.actual_expected_contents('pybind_name_mapping.Class.html'))
self.assertEqual(*self.actual_expected_contents('pybind_name_mapping.submodule.html'))
+
+class TypeLinks(BaseInspectTestCase):
+ def __init__(self, *args, **kwargs):
+ super().__init__(__file__, 'type_links', *args, **kwargs)
+
+ def test(self):
+ self.run_python({
+ 'PYBIND11_COMPATIBILITY': True
+ })
+ self.assertEqual(*self.actual_expected_contents('pybind_type_links.html'))
+ self.assertEqual(*self.actual_expected_contents('pybind_type_links.Foo.html'))