def _test_patch(code): return patch_name(ast.parse(code).body[0])
= "@patch\ndef _f(self:_T): ..."
s '_T._f', _test_patch(s)) test_eq(
doclinks
Create the module index
patch_name
patch_name (o)
If o
is decorated with patch
or patch_to
, return its class-prefix name
= "@patch_to(_T)\ndef _g(self): ..."
s '_T._g', _test_patch(s)) test_eq(
# Get all patched classes when patching with a union
= "@patch\ndef _f(self:_T|_U|_V): ..."
s '_T._f', '_U._f', '_V._f']) test_eq(_test_patch(s), [
# _build_modidx()
Export a notebook
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 |
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 |
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
create_index
create_index (url, pre=None)
Create a documentation index from a sphinx inventory file at url
, with optional prefix pre
= 'https://docs.python.org/3'
url = create_index(url)
syms
for b in syms['builtins']:
= b.split('.')
b if len(b) != 2: continue
= b[1]
b 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:
= 'bad_entry'
name = type('Dist', (), {'key': 'bad_lib'})()
dist def resolve(self): raise AttributeError("Simulated error")
class GoodEntryPoint:
= 'good_entry'
name = type('Dist', (), {'key': 'good_lib'})()
dist 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()]):
= _build_lookup_table()
entries, py_syms
# 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': {}}}
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.
= NbdevLookup()
c 'nbdev.doclinks.NbdevLookup'] c[
('https://nbdev.fast.ai/api/doclinks.html#nbdevlookup',
'nbdev/doclinks.py',
'https://github.com/AnswerDotAI/nbdev/blob/master/nbdev/doclinks.py')
NbdevLookup.doc
NbdevLookup.doc (sym)
Link to docs for sym
Here’s a test suite that verifies the error handling behavior:
'nbdev.doclinks.NbdevLookup') c.doc(
'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.
= NbdevLookup(strip_libs=('nbdev', 'nbdev_numpy'))
c assert c.doc('array').startswith('http')
NbdevLookup.code
NbdevLookup.code (sym)
Link to source code for sym
'fastcore.net.urlsend') NbdevLookup().code(
'https://github.com/AnswerDotAI/fastcore/blob/master/fastcore/net.py#LNone'
NbdevLookup.linkify
NbdevLookup.linkify (md)
= """This is a link to `numpy.array` and to `array()` and to `get_config()` but not a link to `foobar`.
md 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
= """```python
md def foo():
return `bar`
```"""
assert NbdevLookup().linkify(md) == md
# Test builtins
= "`builtins.str.split`"
md NbdevLookup().linkify(md)
'[`builtins.str.split`](https://docs.python.org/3/library/stdtypes.html#str.split)'
# ... now with stripping
= "`str.split` and `str`"
md 'nbdev_stdlib').linkify(md) NbdevLookup(
'[`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
= "`enumerate`, `builtins.enumerate` and `threading.enumerate`"
md 'nbdev_stdlib')).linkify(md) NbdevLookup((
'[`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.
= "`find()`"
md 'nbdev_numpy','nbdev_stdlib')).linkify(md) NbdevLookup((
'[`find()`](https://numpy.org/doc/stable/reference/generated/numpy.char.find.html#numpy.char.find)'
= "`find()`"
md 'nbdev_stdlib','nbdev_numpy')).linkify(md) NbdevLookup((
'[`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
=globals()).linkify('this is an aliased import link `np.array`') NbdevLookup(ns
'this is an aliased import link [`np.array`](https://numpy.org/doc/stable/reference/generated/numpy.array.html#numpy.array)'