doclinks

Generating a documentation index from a module

Create the module index


source

patch_name

 patch_name (o)

If o is decorated with patch or patch_to, return its class-prefix name

def _test_patch(code): return patch_name(ast.parse(code).body[0])
s = "@patch\ndef _f(self:_T): ..."
test_eq('_T._f', _test_patch(s))
s = "@patch_to(_T)\ndef _g(self): ..."
test_eq('_T._g', _test_patch(s))
# Get all patched classes when patching with a union
s = "@patch\ndef _f(self:_T|_U|_V): ..."
test_eq(_test_patch(s), ['_T._f', '_U._f', '_V._f'])
# _build_modidx()

Export a notebook


source

nbglob

 nbglob (path=None, skip_folder_re='^[_.]', file_glob='*.ipynb',
         skip_file_re='^[_.]', key='nbs_path', as_path=False,
         recursive:bool=True, symlinks:bool=True, file_re:str=None,
         folder_re:str=None, skip_file_glob:str=None,
         func:callable=<function join>, ret_folders:bool=False)

Find all files in a directory matching an extension given a config key.

Type Default Details
path pathlib.Path | str path to start searching
skip_folder_re str None Skip folders matching regex,
file_glob str None Only include files matching glob
skip_file_re str None Skip files matching regex
key str nbs_path
as_path bool False
recursive bool True search subfolders
symlinks bool True follow symlinks?
file_re str None Only include files matching regex
folder_re str None Only enter folders matching regex
skip_file_glob str None Skip files matching glob
func callable join function to apply to each matched file
ret_folders bool False return folders, not just files
Returns L Paths to matched files

source

nbglob_cli

 nbglob_cli (path:str=None, symlinks:bool=False, file_glob:str='*.ipynb',
             file_re:str=None, folder_re:str=None,
             skip_file_glob:str=None, skip_file_re:str='^[_.]',
             skip_folder_re:str='^[_.]')

Find all files in a directory matching an extension given a config key.

Type Default Details
path str None Path to notebooks
symlinks bool False Follow symlinks?
file_glob str *.ipynb Only include files matching glob
file_re str None Only include files matching regex
folder_re str None Only enter folders matching regex
skip_file_glob str None Skip files matching glob
skip_file_re str ^[_.] Skip files matching regex
skip_folder_re str ^[_.] Skip folders matching regex

source

nbdev_export

 nbdev_export (path:str=None,
               procs:<tokensnamingtheexportprocessorstouse.>='black_format
               ', symlinks:bool=False, file_glob:str='*.ipynb',
               file_re:str=None, folder_re:str=None,
               skip_file_glob:str=None, skip_file_re:str='^[_.]',
               skip_folder_re:str='^[_.]')

Export notebooks in path to Python modules

Type Default Details
path str None Path or filename
procs <tokens naming the export processors to use.> black_format
symlinks bool False Follow symlinks?
file_glob str *.ipynb Only include files matching glob
file_re str None Only include files matching regex
folder_re str None Only enter folders matching regex
skip_file_glob str None Skip files matching glob
skip_file_re str ^[_.] Skip files matching regex
skip_folder_re str ^[_.] Skip folders matching regex

procs names the optional processors you wish to run on the exported cells of your notebook.

N.B.: the black_format processor is passed in by default. But it is a no-op, unless black_formatting=True is set in your settings.ini configuration. You can omit it from nbdev_export on the command line by passing in --procs.

Construct Index


source

create_index

 create_index (url, pre=None)

Create a documentation index from a sphinx inventory file at url, with optional prefix pre

url = 'https://docs.python.org/3'
syms = create_index(url)

for b in syms['builtins']:
    b = b.split('.')
    if len(b) != 2: continue
    b = b[1]
    assert b in bset

dict(list(syms['builtins'].items())[:10])
{'builtins.bool': 'https://docs.python.org/3/library/functions.html#bool',
 'builtins.bytearray': 'https://docs.python.org/3/library/stdtypes.html#bytearray',
 'builtins.bytes': 'https://docs.python.org/3/library/stdtypes.html#bytes',
 'builtins.complex': 'https://docs.python.org/3/library/functions.html#complex',
 'builtins.dict': 'https://docs.python.org/3/library/stdtypes.html#dict',
 'builtins.float': 'https://docs.python.org/3/library/functions.html#float',
 'builtins.frozenset': 'https://docs.python.org/3/library/stdtypes.html#frozenset',
 'builtins.int': 'https://docs.python.org/3/library/functions.html#int',
 'builtins.list': 'https://docs.python.org/3/library/stdtypes.html#list',
 'builtins.memoryview': 'https://docs.python.org/3/library/stdtypes.html#memoryview'}

Query the module index

Let’s test out our error handling when one of the entry points throws an error:

# Create mock entry points
class BadEntryPoint:
    name = 'bad_entry'
    dist = type('Dist', (), {'key': 'bad_lib'})()
    def resolve(self): raise AttributeError("Simulated error")

class GoodEntryPoint:
    name = 'good_entry'
    dist = type('Dist', (), {'key': 'good_lib'})()
    def resolve(self): return {'syms': {}, 'settings': {}}
# Clear the cache before testing
_build_lookup_table.cache_clear()

# Patch iter_entry_points
with xpatch('pkg_resources.iter_entry_points', return_value=[BadEntryPoint(), GoodEntryPoint()]):
    entries, py_syms = _build_lookup_table()
    
    # Should only contain the good entry
    assert 'bad_entry' not in entries
    assert 'good_entry' in entries
    assert len(entries) == 1
entries
{'good_entry': {'syms': {}, 'settings': {}}}

source

NbdevLookup

 NbdevLookup (strip_libs=None, incl_libs=None, skip_mods=None, ns=None)

Mapping from symbol names to docs and source URLs

Indexing returns a link to the symbol’s docs, along with the name of the source file the source URL if available.

c = NbdevLookup()
c['nbdev.doclinks.NbdevLookup']
('https://nbdev.fast.ai/api/doclinks.html#nbdevlookup',
 'nbdev/doclinks.py',
 'https://github.com/AnswerDotAI/nbdev/blob/master/nbdev/doclinks.py')

source

NbdevLookup.doc

 NbdevLookup.doc (sym)

Link to docs for sym

Here’s a test suite that verifies the error handling behavior:

c.doc('nbdev.doclinks.NbdevLookup')
'https://nbdev.fast.ai/api/doclinks.html#nbdevlookup'

Symbol names are taken from libraries registered using the ‘nbdev’ entry point. By default, all libraries with this entry point are searched, but full symbol names (including module prefix) are required.

assert c.doc('numpy.array').startswith('http')
assert not c.doc('numpy.Array')
assert c.doc('NbdevLookup').endswith('#nbdevlookup')
assert not c.doc('array')

Pass strip_libs to list libraries which should be available without requiring a module prefix.

c = NbdevLookup(strip_libs=('nbdev', 'nbdev_numpy'))
assert c.doc('array').startswith('http')

source

NbdevLookup.code

 NbdevLookup.code (sym)

Link to source code for sym

NbdevLookup().code('fastcore.net.urlsend')
'https://github.com/AnswerDotAI/fastcore/blob/master/fastcore/net.py#LNone'

source

NbdevLookup.linkify

 NbdevLookup.linkify (md)
md = """This is a link to `numpy.array` and to `array()` and to `get_config()` but not a link to `foobar`.
And not a link to <code>dict2nb</code>.

    This is not a link to `get_config`

```
This isn't a link to `get_config` either
```"""
print(NbdevLookup(('nbdev','numpy')).linkify(md))
This is a link to [`numpy.array`](https://numpy.org/doc/stable/reference/generated/numpy.array.html#numpy.array) and to `array()` and to [`get_config()`](https://nbdev.fast.ai/api/config.html#get_config) but not a link to `foobar`.
And not a link to <code>dict2nb</code>.

    This is not a link to `get_config`

```
This isn't a link to `get_config` either
```
# Test code blocks
md = """```python
def foo():
    return `bar`
```"""
assert NbdevLookup().linkify(md) == md
# Test builtins
md = "`builtins.str.split`"
NbdevLookup().linkify(md)
'[`builtins.str.split`](https://docs.python.org/3/library/stdtypes.html#str.split)'
# ... now with stripping
md = "`str.split` and `str`"
NbdevLookup('nbdev_stdlib').linkify(md)
'[`str.split`](https://docs.python.org/3/library/stdtypes.html#str.split) and [`str`](https://docs.python.org/3/library/stdtypes.html#str)'

When there is a conflict, the linkification will apply in the order of the stripped libraries and then by alphabetical order. For example, enumerate is both a builtin and a function in the threading module. However, since builtins comes first alphabetically, it will take priority

md = "`enumerate`, `builtins.enumerate` and `threading.enumerate`"
NbdevLookup(('nbdev_stdlib')).linkify(md)
'[`enumerate`](https://docs.python.org/3/library/functions.html#enumerate), [`builtins.enumerate`](https://docs.python.org/3/library/functions.html#enumerate) and [`threading.enumerate`](https://docs.python.org/3/library/threading.html#threading.enumerate)'

We can also take the find() function as another instance, it exists as a standard library and in numpy. Therefore, depending on the order of stripped libraries we pass, find() will link to either numpy or standard library.

md = "`find()`"
NbdevLookup(('nbdev_numpy','nbdev_stdlib')).linkify(md)
'[`find()`](https://numpy.org/doc/stable/reference/generated/numpy.char.find.html#numpy.char.find)'
md = "`find()`"
NbdevLookup(('nbdev_stdlib','nbdev_numpy')).linkify(md)
'[`find()`](https://docs.python.org/3/library/gettext.html#gettext.find)'

You can also use NbdevLookup with import aliases like the following:

import numpy as np
NbdevLookup(ns=globals()).linkify('this is an aliased import link `np.array`')
'this is an aliased import link [`np.array`](https://numpy.org/doc/stable/reference/generated/numpy.array.html#numpy.array)'