Flags are custom ipython magics, that tell nbdev how to process cells in a notebook.

In this notebook, we test the flags defined in flags.py and show how you can start using them in your notebooks.

Note: Magic flags are being introduced progressively

In order to explore autocomplete and in-notebook help with magic flags we plan to;

  • start by making %nbdev_export available as an alternative to #export
  • support both comments and magic flags

Using magic flags

You can start using magic flags in existing notebooks by running the nbdev_upgrade console command.

If you prefer not to use the nbdev_upgrade console command, you'll need to "import" flags before you can use them. Any nbdev import will import all flags via nbdev.__init__.py. So you could use

  • import nbdev or
  • from nbdev.imports import *

but if you want the convenience of importing show_doc and notebook2script as well, use

from nbdev import *

Once imported, you can explore the available flags and their documentation without leaving your notebook

Tab completion of nbdev magics

Note: In the image above, we show some flags that have not yet been introduced to nbdev.

You can also see that some flags print warnings if used incorrectly

%nbdev_export bad module name
UsageError: module_name "bad module name" must not contain whitespace

Tests

We can test magics in ipython ...

from nbdev.imports import test_eq, IN_IPYTHON
from contextlib import redirect_stdout
import io

if IN_IPYTHON:
    def test_flag_output(s, exp):
        test_eq(s.getvalue().strip(), exp.strip())
    s = io.StringIO()
    with redirect_stdout(s):
        %nbdev_export
        test_flag_output(s, '')
        %nbdev_export other.module
        test_flag_output(s, '')
        %nbdev_export bad module name
        test_flag_output(s, 'UsageError: module_name "bad module name" must not contain whitespace')

... but we need less code to test in normal python

Note: We don't del the functions in flags.py so that we can test them here

def test_flag_output(f, line, exp):
    "Test that `f(line)` prints `exp` to stdout"
    s = io.StringIO()
    with redirect_stdout(s): f(line)
    test_eq(s.getvalue().strip(), exp.strip())

from nbdev.flags import nbdev_default_export
test_flag_output(nbdev_default_export, '', 'UsageError: module_name is missing. Usage `%nbdev_default_export module_name`')
test_flag_output(nbdev_default_export, '  ', 'UsageError: module_name is missing. Usage `%nbdev_default_export module_name`')
test_flag_output(nbdev_default_export, 'bad module name', 'UsageError: module_name "bad module name" must not contain whitespace')
test_flag_output(nbdev_default_export, 'special.module', 
            'Cells will be exported to nbdev.special.module,\n' +
            'unless a different module is specified after an export flag: `%nbdev_export special.module`')

from nbdev.flags import nbdev_export, nbdev_export_and_show, nbdev_export_internal
for f in [nbdev_export, nbdev_export_and_show, nbdev_export_internal]:
    test_flag_output(f, '', '')
    test_flag_output(f, ' ', '')
    test_flag_output(f, 'special.module', '')
    test_flag_output(f, 'bad module name', 'UsageError: module_name "bad module name" must not contain whitespace')
    
from nbdev.flags import nbdev_fastai2_test
test_flag_output(nbdev_fastai2_test, '', '')
test_flag_output(nbdev_fastai2_test, ' ', '')
test_flag_output(nbdev_fastai2_test, 'all', '')
test_flag_output(nbdev_fastai2_test, 'All', 'UsageError: Invalid option "All". Usage `%nbdev_fastai2_test [all]`')

from nbdev.flags import nbdev_collapse_input, nbdev_collapse_output
for f in [nbdev_collapse_input, nbdev_collapse_output]:
    test_flag_output(f, '', '')
    test_flag_output(f, ' open ', '')
    test_flag_output(f, 'open', '')
    test_flag_output(f, 'OPEN', f'UsageError: Invalid option "OPEN". Usage `%{f.__name__} [open]`')