from __future__ import annotations
All the automatic documentation of functions and classes are generated with the show_doc
function. It displays the name, arguments, docstring along with a link to the source code on GitHub.
The inspect module lets us know quickly if an object is a function or a class but it doesn't distinguish classes and enums.
e = enum.Enum('e', 'a b')
assert is_enum(e)
assert not is_enum(e.__class__)
assert not is_enum(int)
assert is_lib_module('export')
assert not is_lib_module('transform')
This function will only work for other packages built with nbdev
.
test_eq(try_external_doc_link('get_name', ['nbdev']), 'https://nbdev.fast.ai/sync#get_name')
test_eq(is_doc_name('flaags'),False)
test_eq(is_doc_name('export'),True)
test_eq(is_doc_name('index'),True)
This function will generate links for modules (pointing to the html conversion of the corresponding notebook) and functions (pointing to the html conversion of the notebook where they were defined, with the first anchor found before). If the function/module is not part of the library you are writing, it will call the function custom_doc_links
generated in _nbdev
(you can customize it to your needs) and just return the name between backticks if that function returns None
.
For instance, fastai has the following custom_doc_links
that tries to find a doc link for name
in fastcore then nbdev (in this order):
def custom_doc_links(name):
from nbdev.showdoc import try_external_doc_link
return try_external_doc_link(name, ['fastcore', 'nbdev'])
Please note that module links only work if your notebook names "correspond" to your module names:
Notebook name | Doc name | Module name | Module file | Can doc link? |
---|---|---|---|---|
export.ipynb | export.html | export | export.py | Yes |
00_export.ipynb | export.html | export | export.py | Yes |
00a_export.ipynb | export.html | export | export.py | Yes |
export_1.ipynb | export_1.html | export | export.py | No |
03_data.core.ipynb | data.core.html | data.core | data/core.py | Yes |
03_data_core.ipynb | data_core.html | data.core | data/core.py | No |
test_eq(doc_link('export'), f'[`export`](/export.html)')
test_eq(doc_link('DocsTestClass'), f'[`DocsTestClass`](/export.html#DocsTestClass)')
test_eq(doc_link('DocsTestClass.test'), f'[`DocsTestClass.test`](/export.html#DocsTestClass.test)')
test_eq(doc_link('Tenso'),'`Tenso`')
test_eq(doc_link('_nbdev'), f'`_nbdev`')
test_eq(doc_link('__main__'), f'`__main__`')
test_eq(doc_link('flags'), '`flags`') # we won't have a flags doc page even though we do have a flags module
This function not only add links to backtick keywords, it also update the links that are already in the text (in case they have changed).
tst = add_doc_links('This is an example of `DocsTestClass`')
test_eq(tst, "This is an example of [`DocsTestClass`](/export.html#DocsTestClass)")
tst = add_doc_links('This is an example of [`DocsTestClass`](old_link.html)')
test_eq(tst, "This is an example of [`DocsTestClass`](/export.html#DocsTestClass)")
Names in backticks will not be converted to links if elt
has a parameter of the same name
def t(a,export):
"Test func that uses 'export' as a parameter name and has `export` in its doc string"
assert '[`export`](/export.html)' not in add_doc_links(t.__doc__, t)
Names in backticks used in markdown links will be updated like normal
def t(a,export):
"Test func that uses 'export' as a parameter name and has [`export`]() in its doc string"
assert '[`export`](/export.html)' in add_doc_links(t.__doc__, t)
If elt
is a class, add_doc_links
looks at parameter names used in __init__
class T:
def __init__(self, add_doc_links): pass
test_eq(add_doc_links('Lets talk about `add_doc_links`'),
'Lets talk about [`add_doc_links`](/showdoc.html#add_doc_links)')
test_eq(add_doc_links('Lets talk about `add_doc_links`', T), 'Lets talk about `add_doc_links`')
test_eq(add_doc_links('Lets talk about `doc_link`'),
'Lets talk about [`doc_link`](/showdoc.html#doc_link)')
test_eq(add_doc_links('Lets talk about `doc_link`', T),
'Lets talk about [`doc_link`](/showdoc.html#doc_link)')
As important as the source code, we want to quickly jump to where the function is defined when we are in a development notebook.
colab_link('02_showdoc')
test_eq(get_nb_source_link(DocsTestClass.test), get_nb_source_link(DocsTestClass))
test_eq(get_nb_source_link('DocsTestClass'), get_nb_source_link(DocsTestClass))
test_eq(get_nb_source_link(check_re, local=True), f'00_export.ipynb#Finding-patterns')
You can either pass an object or its name (by default is_name
will look if func
is a string or not to decide if it's True
or False
, but you can override if there is some inconsistent behavior). local
will return a local link, otherwise it will point to a the notebook on Google Colab.
This function assumes you are in one notebook in the development folder, otherwise you can use disp=False
to get the relative link. You can either pass an object or its name (by default is_name
will look if func
is a string or not to decide if it's True
or False
, but you can override if there is some inconsistent behavior).
test_eq(nb_source_link(check_re, disp=False), f'00_export.ipynb#Finding-patterns')
test_eq(nb_source_link('check_re', disp=False), f'00_export.ipynb#Finding-patterns')
nb_source_link(check_re, local=False)
The representation tries to find doc links if possible.
tst = type_repr(Optional[DocsTestClass])
test_eq(tst, '`Optional`\\[[`DocsTestClass`](/export.html#DocsTestClass)\\]')
tst = type_repr(Union[int, float])
test_eq(tst, '`Union`\\[`int`, `float`\\]')
test_eq(type_repr(Param("description")), '"description"')
sig = inspect.signature(notebook2script)
params = [format_param(p) for _,p in sig.parameters.items()]
test_eq(params, ['**`fname`**=*`None`*', '**`silent`**=*`False`*', '**`to_dict`**=*`False`*', '**`bare`**=*`False`*'])
def o(a:list|int): return a
sig = inspect.signature(o)
params = [format_param(p) for _,p in sig.parameters.items()]
test_eq(params, ['**`a`**:`list | int`'])
doc_string
determines if we show the docstring of the function or not. name
can be used to provide an alternative to the name automatically found. title_level
determines the level of the anchor (default 3 for classes and 4 for functions). If disp
is False
, the function returns the markdown code instead of displaying it. If doc_string
is True
and monospace_docstrings
is set to True
in settings.ini
, the docstring of the function is formatted in a code block to preserve whitespace.
For instance
show_doc(notebook2script)
will display
test_eq(get_doc_link(notebook2script), 'https://nbdev.fast.ai/export#notebook2script')
from nbdev.sync import get_name
test_eq(get_doc_link(get_name), 'https://nbdev.fast.ai/sync#get_name')