find_var
find_var (lines, varname)
Find the line numbers where varname
is defined in lines
These functions let us find and modify the definitions of variables in python modules.
find_var (lines, varname)
Find the line numbers where varname
is defined in lines
read_var (code, varname)
Eval and return the value of varname
defined in code
update_var (varname, func, fn=None, code=None)
Update the definition of varname
in file fn
, by calling func
with the current definition
ModuleMaker (dest, name, nb_path, is_new=True, parse=True)
Helper class to create exported library from notebook source cells
In order to export a notebook, we need an way to create a Python file. ModuleMaker fills that role. Pass in the directory where you want to module created, the name of the module, the path of the notebook source, and set is_new
to True
if this is a new file being created (rather than an existing file being added to). The location of the saved module will be in fname
. Finally, if the source in the notebooks should not be parsed by python (such as partial class declarations in cells), parse
should be set to False
.
Note: If doing so, then the
__all__
generation will be turned off as well.
mm = ModuleMaker(dest='tmp', name='test.testing', nb_path=Path.cwd()/'01_export.ipynb', is_new=True)
mm.fname
Path('tmp/test/testing.py')
decor_id (d)
id
attr of decorator, regardless of whether called as function or bare
retr_exports (trees)
ModuleMaker.make_all (cells)
Create __all__
with all exports in cells
make_code_cells (*ss)
make_code_cell (code)
We want to add an __all__
to the top of the exported module. This methods autogenerates it from all code in cells
.
relative_import (name, fname, level=0)
Convert a module name
to a name relative to fname
test_eq(relative_import('nbprocess.core', "xyz"), 'nbprocess.core')
test_eq(relative_import('nbprocess.core', 'nbprocess'), '.core')
_p = Path('fastai')
test_eq(relative_import('fastai.core', _p/'vision'), '..core')
test_eq(relative_import('fastai.core', _p/'vision/transform'), '...core')
test_eq(relative_import('fastai.vision.transform', _p/'vision'), '.transform')
test_eq(relative_import('fastai.notebook.core', _p/'data'), '..notebook.core')
test_eq(relative_import('fastai.vision', _p/'vision'), '.')
NbCell.import2relative (cell:execnb.nbio.NbCell, libname)
update_import (source, tree, libname, f=<functionrelative_importat0x7fc8c216ab90>)
ss = "from nbprocess.export import *\nfrom nbprocess.a.b import *"
cell = make_code_cells([ss])[0]
cell.import2relative('nbprocess')
test_eq(cell.source, 'from .export import *\nfrom .a.b import *')
cell = make_code_cells([ss])[0]
cell.import2relative('nbprocess/a')
test_eq(cell.source, 'from ..export import *\nfrom .b import *')
ModuleMaker.make (cells, all_cells=None, lib_name=None)
Write module containing cells
with __all__
generated from all_cells
cells = make_code_cells("from __future__ import print_function", "#|export\ndef a(): ...", "def b(): ...")
mm.make(cells, L([cells[1]]))
print(Path('tmp/test/testing.py').read_text())
# AUTOGENERATED! DO NOT EDIT! File to edit: ../01_export.ipynb.
# %% ../01_export.ipynb 0
from __future__ import print_function
# %% auto 0
__all__ = ['a']
# %% ../01_export.ipynb 2
#|export
def a(): ...
# %% ../01_export.ipynb 3
def b(): ...
Pass all_cells=[]
or parse=False
if you don’t want any __all__
added.
Passing parse=False
is also handy for when writing broken up functions or classes that ast.parse might not like but still want it to be exported, such as having once cell with the contents of:
Note that by doing so we cannot properly generate a __all__
, so we assume that it is unwanted.
am = ModuleMaker(dest='tmp', name='test.testing_noall', nb_path=Path.cwd()/'01_export.ipynb', is_new=True, parse=False)
am.fname
Path('tmp/test/testing_noall.py')
cells = make_code_cells("from __future__ import print_function", "#|export\ndef a(): ...", "#|export\nclass A:")
am.make(cells)
print(Path('tmp/test/testing_noall.py').read_text())
# AUTOGENERATED! DO NOT EDIT! File to edit: ../01_export.ipynb.
# %% ../01_export.ipynb 0
from __future__ import print_function
# %% ../01_export.ipynb 1
#|export
def a(): ...
# %% ../01_export.ipynb 2
#|export
class A:
If is_new=False
then the additional definitions are added to the bottom, and any existing __all__
is updated with the newly-added symbols.
# AUTOGENERATED! DO NOT EDIT! File to edit: ../01_export.ipynb.
# %% ../01_export.ipynb 0
from __future__ import print_function
# %% auto 0
__all__ = ['a', 'c', 'd']
# %% ../01_export.ipynb 2
#|export
def a(): ...
# %% ../01_export.ipynb 3
def b(): ...
# %% ../01_export.ipynb 0
def c(): ...
# %% ../01_export.ipynb 1
def d(): ...
basic_export_nb2 (fname, name, dest=None)
A basic exporter to bootstrap nbprocess using ModuleMaker
path = Path('../nbprocess')
(path/'read.py').unlink(missing_ok=True)
(path/'maker.py').unlink(missing_ok=True)
add_init(path)
cfg = get_config()
basic_export_nb2('01_read.ipynb', 'read')
basic_export_nb2('02_maker.ipynb', 'maker')
g = exec_import('nbprocess', 'maker')
assert g['maker'].ModuleMaker
assert 'ModuleMaker' in g['maker'].__all__