config

Configuring nbdev and bootstrapping notebook export

Configuring nbdev

nbdev is heavily customizeable, thanks to the configuration system defined in this module. There are 2 ways to interact with nbdev’s config:

Read on for more about how these work.


source

nbdev_create_config


def nbdev_create_config(
    repo:str=None, # Repo name
    branch:str=None, # Repo default branch
    user:str=None, # Repo username
    author:str=None, # Package author's name
    author_email:str=None, # Package author's email address
    description:str=None, # Short summary of the package
    path:str='.', # Path to create config file
    cfg_name:str='settings.ini', # Name of config file to create
    lib_name:str='%(repo)s', # Package name
    git_url:str='https://github.com/%(user)s/%(repo)s', # Repo URL
    custom_sidebar:bool_arg=False, # Use a custom sidebar.yml?
    nbs_path:Path='nbs', # Path to notebooks
    lib_path:Path=None, # Path to package root (default: `repo` with `-` replaced by `_`)
    doc_path:Path='_docs', # Path to rendered docs
    tst_flags:str='notest', # Test flags
    version:str='0.0.1', # Version of this release
    doc_host:str='https://%(user)s.github.io', # Hostname for docs
    doc_baseurl:str='/%(repo)s', # Base URL for docs
    keywords:str='nbdev jupyter notebook python', # Package keywords
    license:str='apache2', # License for the package
    copyright:str=None, # Copyright for the package, defaults to '`current_year` onwards, `author`'
    status:str='3', # Development status PyPI classifier
    min_python:str='3.9', # Minimum Python version PyPI classifier
    audience:str='Developers', # Intended audience PyPI classifier
    language:str='English', # Language PyPI classifier
    recursive:bool_arg=True, # Include subfolders in notebook globs?
    black_formatting:bool_arg=False, # Format libraries with black?
    readme_nb:str='index.ipynb', # Notebook to export as repo readme
    title:str='%(lib_name)s', # Quarto website title
    allowed_metadata_keys:str='', # Preserve the list of keys in the main notebook metadata
    allowed_cell_metadata_keys:str='', # Preserve the list of keys in cell level metadata
    jupyter_hooks:bool_arg=False, # Run Jupyter hooks?
    clean_ids:bool_arg=True, # Remove ids from plaintext reprs?
    clear_all:bool_arg=False, # Remove all cell metadata and cell outputs?
    cell_number:bool_arg=True, # Add cell number to the exported file
    put_version_in_init:bool_arg=True, # Add the version to the main __init__.py in nbdev_export
    update_pyproject:bool_arg=True, # Create/update pyproject.toml with correct project name
    skip_procs:str='', # A comma-separated list of processors that you want to skip
):

Create a config file.

The table above also serves as a full reference of nbdev’s settings (excluding the path and cfg_name parameters which decide where the config file is saved). For more about PyPI classifiers, see Classifiers.

You can create a config file by passing all of the required settings via the command line, as well as any optional settings you’d like to override, for example:

nbdev_create_config --repo nbdev --user fastai --author fastai \
                    --author_email [email protected] --description 'A test project'

If you don’t provide required settings from the command line, we’ll try to to infer them from git and GitHub. Finally, you’ll be asked to manually input any required settings that we couldn’t automatically fill in.


source

get_config


def get_config(
    cfg_name:str='settings.ini', path:NoneType=None
):

Return nbdev config.

Searches up from path until cfg_name is found. User settings are loaded from ~/.config/nbdev/{cfg_name}. Unspecified optional settings return defaults.

See nbdev_create_config for a full reference of nbdev’s settings.

cfg = get_config()

cfg is a fastcore Config object, so you can access keys as attributes:

p = Path.cwd().parent.parent
test_eq(cfg.lib_name, 'nbdev')
test_eq(cfg.git_url, 'https://github.com/AnswerDotAI/nbdev')

Its own path and parent are attributes too:

test_eq(cfg.config_path, p)
test_eq(cfg.config_file, p/'settings.ini')

Paths are relative to the project:

test_eq(cfg.doc_path, p/'_docs')
test_eq(cfg.lib_path, p/'nbdev')
test_eq(cfg.nbs_path, p/'nbs')

It automatically returns defaults for keys not specified in the config file. Here we create an empty config file and access lib_path and copyright even though they weren’t explicitly defined:

with tempfile.TemporaryDirectory() as d, working_directory(d):
    Config('.', 'test_settings.ini', {'repo': 'my-project', 'author': 'fastai', 'nbs_path': 'nbs'});
    cfg = get_config('test_settings.ini', '.')
    test_eq(cfg.repo, 'my-project')
    test_eq(cfg.lib_path.name, 'my_project')

In fact, you can return a default config even if you don’t have a settings file. This is to support certain nbdev commands work outside of nbdev repos:

cfg = get_config('test_settings.ini', '.')
test_eq(cfg.lib_path, Path('nbdev').resolve())
test_eq(cfg.nbs_path, Path('nbs').resolve())

You can customise nbdev for all repositories for your user with a ~/.config/nbdev/settings.ini file (by default, although we follow the broader XDG specification). For example, you could globally disable nbdev’s Jupyter hooks by creating a user settings file with jupyter_hooks = False.


source

config_key


def config_key(
    c, default:NoneType=None, path:bool=True, missing_ok:NoneType=None
):

Deprecated: use get_config().get or get_config().path instead.

Helpers


source

is_nbdev


def is_nbdev(
    
):

source

create_output


def create_output(
    txt, mime
):

Add a cell output containing txt of the mime text MIME sub-type


source

show_src


def show_src(
    src, lang:str='python'
):
show_src("print(create_output('text', 'text/plain'))")
print(create_output('text', 'text/plain'))

Exporting a basic module


source

add_init


def add_init(
    path:NoneType=None
):

Add __init__.py in all subdirs of path containing python files if it’s not there already.


source

update_proj


def update_proj(
    path
):

Create or update pyproject.toml in the project root.


source

update_version


def update_version(
    path:NoneType=None
):

Add or update __version__ in the main __init__.py of the library.

Python modules require a __init.py__ file in all directories that are modules. We assume that all directories containing a python file (including in subdirectories of any depth) is a module, and therefore add a __init__.py to each.

with tempfile.TemporaryDirectory() as d:
    d = Path(d)
    (d/'a/b').mkdir(parents=True)
    (d/'a/b/f.py').touch()
    (d/'a/c').mkdir()
    add_init(d)
    assert not (d/'a/c'/_init).exists(), "Should not add init to dir without py file"
    for e in [d, d/'a', d/'a/b']: assert (e/_init).exists(),f"Missing init in {e}"

source

write_cells


def write_cells(
    cells, hdr, file, offset:int=0, cell_number:bool=True, solo_nb:bool=False
):

Write cells to file along with header hdr starting at index offset (mainly for nbdev internal use).

This is a simple exporter with just enough functionality to correctly export this notebook, in order to bootstrap the creation of nbdev itself.