Welcome to flake8-nb’s documentation!

flake8-nb

PyPi Version Conda Version Supported Python Versions Pre-commit License

Actions Status Documentation Status Testing Coverage Documentation Coverage

Codacy Badge All Contributors Code style Python: black Binder

flake8 checking for jupyter notebooks.

This tool is mainly aimed towards writing tutorials/lecture material, where one might also want to show off bad practices and/or errors, while still keeping the rest of the code clean and without adding the complexity of tooling to the readers (see docs on cell tags).

Basically this is a hack on the flake8’s Application class, which adds parsing and a cell based formatter for *.ipynb files.

This is NOT A PLUGIN but a stand alone CLI tool/pre-commit hook to be used instead of the flake8 command/hook.

Features

  • flake8 CLI tests for jupyter notebooks

  • Full base functionality of flake8 and its plugins

  • Input cell based error formatting (Execution count/code cell count/total cellcount)

  • Report fine tuning with cell-tags (flake8-noqa-tags see usage)

  • pre-commit hook

Examples

Default reporting

If you had a notebook with name example_notebook.ipynb, where the code cell which was executed as 34th cell (In[34]) had the following code:

bad_formatted_dict = {"missing":"space"}

running flake8_nb would result in the following output.

Execution count

$ flake8_nb example_notebook.ipynb
example_notebook.ipynb#In[34]:1:31: E231 missing whitespace after ':'

Custom reporting

If you prefer the reports to show the cell number rather then the execution count you can use the --notebook-cell-format option, given that the cell is the 5th code cell and 10th total cell (taking raw and markdown cells into account), you will get the following output.

Code cell count

$ flake8_nb --notebook-cell-format '{nb_path}:code_cell#{code_cell_count}' example_notebook.ipynb
example_notebook.ipynb:code_cell#5:1:31: E231 missing whitespace after ':'

Total cell count

$ flake8_nb --notebook-cell-format '{nb_path}:cell#{total_cell_count}' example_notebook.ipynb
example_notebook.ipynb:cell#10:1:31: E231 missing whitespace after ':'

Similar projects

  • nbQA: Run isort, pyupgrade, mypy, pylint, flake8, mdformat, black, blacken-docs, and more on Jupyter Notebooks

Contributors ✨

Thanks goes to these wonderful people (emoji key):

Sebastian Weigand
Sebastian Weigand

💻 🤔 🚧 📆 🚇 ⚠️ 📖
Jt Miclat
Jt Miclat

🐛
Philipp Eisenhauer
Philipp Eisenhauer

🐛
Shoma Okamoto
Shoma Okamoto

⚠️
Marco Gorelli
Marco Gorelli

🔧 📖
Tony Hirst
Tony Hirst

🤔
Dobatymo
Dobatymo

🐛
Alp Arıbal
Alp Arıbal

🐛
1kastner
1kastner

🐛
Dominique Sydow
Dominique Sydow

🐛
Liam Keegan
Liam Keegan

🐛 💻

This project follows the all-contributors specification. Contributions of any kind welcome!

Installation

Stable release

To install flake8-nb, run this command in your terminal:

$ pip install flake8-nb

This is the preferred method to install flake8-nb, as it will always install the most recent stable release.

If you don’t have pip installed, this Python installation guide can guide you through the process.

From sources

You can either pip install it directly from github:

$ pip install git+git://github.com/s-weigand/flake8-nb@<branch_name>

Or get the sources for flake8-nb, which can be downloaded from the Github repo.

By cloning the public repository:

$ git clone git://github.com/s-weigand/flake8-nb

Or downloading the tarball:

$ curl -OJL https://github.com/s-weigand/flake8-nb/tarball/main

Once you have a copy of the source, you can install it with:

$ python setup.py install

Usage

Since flake8_nb is basically a hacked version of flake8 its usage is identically. The only key difference is the appended _nb is the commands and configurations name.

Command line usage

The basic usage is to call flake8_nb with the files/paths, which should be checked as arguments (see flake8 invocation).

$ flake8_nb path-to-notebooks-or-folder

To customize the behavior you can use the many options provided by flake8’s CLI. To see all the provided option just call:

$ flake8_nb --help

Additional flags/options provided by flake8_nb:

  • --keep-parsed-notebooks

    If this flag is activated the the parsed notebooks will be kept and the path they were saved in will be displayed, for further debugging or trouble shooting.

  • --notebook-cell-format

    Template string used to format the filename and cell part of error report. Possible variables which will be replaced are nb_path, exec_count, code_cell_count and total_cell_count.

Project wide configuration

Configuration of a project can be saved in one of the following files setup.cfg, tox.ini or .flake8_nb, on the top level of your project (see flake8 configuration).

[flake8_nb]
; Default values
keep_parsed_notebooks = False
notebook_cell_format = {nb_path}#In[{exec_count}]

For a detailed explanation on how to use and configure it, you can consult the official flake8 documentation

Per cell/line configuration

There are multiple ways to fine grade configure flake8_nb on a line or cell basis.

flake8 noqa comments

The most intuitive way for experienced flake8 users is to utilize the known flake8 noqa comment on a line, to ignore specific or all errors, flake8 would report on that given line.

Note

If a normal flake8 noqa comment ends with a string, which doesn’t match the error code pattern (\w+\d+), this comment will be ignored.

Cell tags

Cell tags are meta information, which can be added to cells, to augment their behavior (for jupyterlab<2.0, you will need to install jupyterlab-celltags ). Depending on the editor you use for the notebook, they aren’t directly visible, which is a nice way to hide certain internals which aren’t important for the user/reader. For example if write a book like notebook and want to demonstrate some bad code examples an still pass your flake8_nb tests you can use flake8-noqa-tags. Or if you want to demonstrate a raised exception and still want then whole notebook to be executed when you run all cells, you can use the raises-exception tag.

The patterns for flake8-noqa-tags are the following:

  • flake8-noqa-cell

    ignores all reports from a cell

  • flake8-noqa-cell-<rule1>-<rule2>

    ignores given rules for the cell i.e. flake8-noqa-cell-F401-F811

  • flake8-noqa-line-<line_nr>

    ignores all reports from a given line in a cell, i.e. flake8-noqa-line-1

  • flake8-noqa-line-<line_nr>-<rule1>-<rule2>

    ignores given rules from a given line for the cell i.e. flake8-noqa-line-1-F401-F811

Inline cell tags

If you want your users/reader to directly see which flake8 rules are ignored, you can also use the flake8-noqa-tag pattern as comment in a cell.

Note

If you use jupyter magic to run code other than Python (i.e. %%bash) you should ignore the whole cell with flake8-noqa-cell.

As pre-commit hook

Add the following to your .pre-commit-config.yaml file:

- repo: https://github.com/s-weigand/flake8-nb
  rev: 0.5.3 # specify version here
  hooks:
  - id: flake8-nb

See pre-commit docs for more on pre-commit.

Examples

This page was generated from tests/data/notebooks/notebook_with_out_flake8_tags.ipynb. Interactive online version: Binder badge # noqa: E501

This notebook demonstrates flake8_nb reporting

The next cell should report F401 'not_a_package' imported but unused

[1]:
import not_a_package
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-1-d9fbe3554078> in <module>
----> 1 import not_a_package

ModuleNotFoundError: No module named 'not_a_package'

The next cell should report E231 missing whitespace after ':'

[2]:
{"1":1}
[2]:
{'1': 1}

The next cell should not be reported, since it is valid syntax

[3]:
def func():
    return "foo"

The next cell should not be reported, since it is valid syntax

[4]:
class Bar:
    def foo(self):
        return "foo"

The next cell should be ignored in the generated intermediate *.py file since it is empty

[ ]:

The next cell should report E231 missing whitespace after ':'

[5]:
{"1":1}
[5]:
{'1': 1}

Report using execution count

[6]:
!flake8_nb notebook_with_out_flake8_tags.ipynb
notebook_with_out_flake8_tags.ipynb#In[1]:1:1: F401 'not_a_package' imported but unused
notebook_with_out_flake8_tags.ipynb#In[2]:1:5: E231 missing whitespace after ':'
notebook_with_out_flake8_tags.ipynb#In[5]:1:5: E231 missing whitespace after ':'

Report using code cell count

[7]:
!flake8_nb --notebook-cell-format '{nb_path}:code_cell#{code_cell_count}' notebook_with_out_flake8_tags.ipynb
'notebook_with_out_flake8_tags.ipynb:code_cell#1':1:1: F401 'not_a_package' imported but unused
'notebook_with_out_flake8_tags.ipynb:code_cell#2':1:5: E231 missing whitespace after ':'
'notebook_with_out_flake8_tags.ipynb:code_cell#6':1:5: E231 missing whitespace after ':'

Report using total cell count

[8]:
!flake8_nb --notebook-cell-format '{nb_path}:cell#{total_cell_count}' notebook_with_out_flake8_tags.ipynb
'notebook_with_out_flake8_tags.ipynb:cell#3':1:1: F401 'not_a_package' imported but unused
'notebook_with_out_flake8_tags.ipynb:cell#5':1:5: E231 missing whitespace after ':'
'notebook_with_out_flake8_tags.ipynb:cell#14':1:5: E231 missing whitespace after ':'

This page was generated from tests/data/notebooks/notebook_with_flake8_tags.ipynb. Interactive online version: Binder badge # noqa: E501

This notebook demonstrates flake8_nb reporting with flake8-tags

Testing Celltags

The next cell should not report F401 'not_a_package' imported but unused, due to the cell tag flake8-noqa-cell-F401.

But it will report E231 missing whitespace after ':', for line 2.

[1]:
import not_a_package
{"1":1}
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-1-e5f2776a04db> in <module>
----> 1 import not_a_package
      2 {"1":1}

ModuleNotFoundError: No module named 'not_a_package'

The next cell should not report E231 missing whitespace after ':' for line 1, due to the line tag flake8-noqa-line-1-E231.

But it will report E231 missing whitespace after ':', for line 2.

[2]:
{"2":1}
{"2":2}
[2]:
{'2': 2}

The next cell should not report E231 missing whitespace after ':', due to the line tag flake8-noqa-cell-E231.

[3]:
{"3":1}
{"3":2}
[3]:
{'3': 2}

Testing inline Celltags

The next cell should not report F401 'not_a_package' imported but unused, F811 redefinition of unused 'not_a_package' and E402 module level import not at top of file, due to the inline cell tag flake8-noqa-cell-E402-F401-F811.

But it will report E231 missing whitespace after ':', for line 3.

[4]:
# flake8-noqa-cell-E402-F401-F811
import not_a_package
{"4":1}
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-4-4da0e31bdfa0> in <module>
      1 # flake8-noqa-cell-E402-F401-F811
----> 2 import not_a_package
      3 {"4":1}

ModuleNotFoundError: No module named 'not_a_package'

The next cell should not report E231 missing whitespace after ':' for line 2, due to the inline line tag flake8-noqa-line-2-E231.

But it will report E231 missing whitespace after ':', for line 3.

[5]:
# flake8-noqa-line-2-E231
{"5":1}
{"5":2}
[5]:
{'5': 2}

The next cell should not report E231 missing whitespace after ':', due to the inline cell tag flake8-noqa-cell-E231.

[6]:
# flake8-noqa-cell-E231
{"6":1}
{"6":2}
[6]:
{'6': 2}

Testing normal flake8 noqa comments

The next cell should not report E231 missing whitespace after ':' for line 1, due to the flake8 noqa comment #noqa: E231.

But it will report E231 missing whitespace after ':', for line 2.

[7]:
{"5":1}  # noqa: E231
{"5":2}
[7]:
{'5': 2}

Report using execution count

[8]:
!flake8_nb notebook_with_flake8_tags.ipynb
notebook_with_flake8_tags.ipynb#In[1]:2:5: E231 missing whitespace after ':'
notebook_with_flake8_tags.ipynb#In[2]:2:5: E231 missing whitespace after ':'
notebook_with_flake8_tags.ipynb#In[4]:3:5: E231 missing whitespace after ':'
notebook_with_flake8_tags.ipynb#In[5]:3:5: E231 missing whitespace after ':'
notebook_with_flake8_tags.ipynb#In[7]:2:5: E231 missing whitespace after ':'

Report using code cell count

[9]:
!flake8_nb --notebook-cell-format '{nb_path}:code_cell#{code_cell_count}' notebook_with_flake8_tags.ipynb
'notebook_with_flake8_tags.ipynb:code_cell#1':2:5: E231 missing whitespace after ':'
'notebook_with_flake8_tags.ipynb:code_cell#2':2:5: E231 missing whitespace after ':'
'notebook_with_flake8_tags.ipynb:code_cell#4':3:5: E231 missing whitespace after ':'
'notebook_with_flake8_tags.ipynb:code_cell#5':3:5: E231 missing whitespace after ':'
'notebook_with_flake8_tags.ipynb:code_cell#7':2:5: E231 missing whitespace after ':'

Report using total cell count

[10]:
!flake8_nb --notebook-cell-format '{nb_path}:cell#{total_cell_count}' notebook_with_flake8_tags.ipynb
'notebook_with_flake8_tags.ipynb:cell#4':2:5: E231 missing whitespace after ':'
'notebook_with_flake8_tags.ipynb:cell#6':2:5: E231 missing whitespace after ':'
'notebook_with_flake8_tags.ipynb:cell#11':3:5: E231 missing whitespace after ':'
'notebook_with_flake8_tags.ipynb:cell#13':3:5: E231 missing whitespace after ':'
'notebook_with_flake8_tags.ipynb:cell#18':2:5: E231 missing whitespace after ':'

Inner workings

This is the detailed documentation of the inner workings of flake8_nb.

flake8_nb

Top-level package for flake8-nb.

Contributing

Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given.

You can contribute in many ways:

Types of Contributions

Report Bugs

Report bugs at https://github.com/s-weigand/flake8-nb/issues.

If you are reporting a bug, please include:

  • Your operating system name and version.

  • Any details about your local setup that might be helpful in troubleshooting.

  • Detailed steps to reproduce the bug.

Fix Bugs

Look through the GitHub issues for bugs. Anything tagged with “bug” and “help wanted” is open to whoever wants to implement it.

Implement Features

Look through the GitHub issues for features. Anything tagged with “enhancement” and “help wanted” is open to whoever wants to implement it.

Write Documentation

flake8-nb could always use more documentation, whether as part of the official flake8-nb docs, in docstrings, or even on the web in blog posts, articles, and such.

Submit Feedback

The best way to send feedback is to file an issue at https://github.com/s-weigand/flake8-nb/issues.

If you are proposing a feature:

  • Explain in detail how it would work.

  • Keep the scope as narrow as possible, to make it easier to implement.

  • Remember that this is a volunteer-driven project, and that contributions are welcome :)

Get Started!

Ready to contribute? Here’s how to set up flake8_nb for local development.

  1. Fork the flake8_nb repo on GitHub.

  2. Clone your fork locally:

    $ git clone git@github.com:your_name_here/flake8_nb.git
    
  3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:

    $ mkvirtualenv flake8_nb
    $ cd flake8_nb/
    $ pip install -r requirements_dev.txt
    $ pip install -e .
    
  4. Install the pre-commit hooks, for quality assurance:

    $ pre-commit install
    
  5. Create a branch for local development:

    $ git checkout -b name-of-your-bugfix-or-feature
    

    Now you can make your changes locally.

  6. When you’re done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox:

    $ tox
    

    To get flake8 and tox, just pip install them into your virtualenv.

  7. Commit your changes and push your branch to GitHub:

    $ git add .
    $ git commit -m "Your detailed description of your changes."
    $ git push origin name-of-your-bugfix-or-feature
    
  8. Submit a pull request through the GitHub website.

Pull Request Guidelines

Before you submit a pull request, check that it meets these guidelines:

  1. The pull request should include tests.

  2. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.rst.

  3. The pull request should work for Python 3.7, 3.8, 3.9 and 3.10. Check https://github.com/s-weigand/flake8-nb/actions and make sure that the tests pass for all supported Python versions.

Tips

To run a subset of tests:

$ pytest tests.test_flake8_nb

Deploying

A reminder for the maintainers on how to deploy. Make sure all your changes are committed (including an entry in HISTORY.rst). Then run:

$ bump2version patch # possible: major / minor / patch
$ git push
$ git push --tags

Travis will then deploy to PyPI if tests pass.

Credits

Many thanks go to the creators and contributors of flake8. Which inspired me to write this hack on top of it and supplies nearly all of the functionality.

This packages skeleton was created with Cookiecutter and the audreyr/cookiecutter-pypackage project template.

The idea to use cell tags was inspired by the use of cell tags in nbval.

Changelog

0.5.3 (2023-03-28)

  • ✨ Official python 3.11 support #291

  • 🩹 Fixed bug with pre-commit-ci due to read-only filesystem by @lkeegan in #290

0.5.2 (2022-08-17)

  • 🩹 Fix config file discovery with flake8>=5.0.0 #255

0.5.1 (2022-08-16)

  • 🩹 Fix config discovery with flake8>=5.0.0 #251

0.5.0 (2022-08-15)

  • Drop support for flake8<3.8.0 #240

  • Set max supported version of flake8 to be <5.0.5 #240

  • Enable calling flake8_nb as python module #240

0.4.0 (2022-02-21)

  • Drop official python 3.6 support

0.3.1 (2021-10-19)

  • Set max supported version of flake8 to be <4.0.2

  • Added official Python 3.10 support and tests

0.3.0 (2020-05-16)

  • Set max supported version of flake8 to be <3.9.3

  • Report formatting is configurable via --notebook-cell-format option with formatting options nb_path, exec_count, code_cell_count and total_cell_count.

0.2.7 (2020-04-16)

  • Set max supported version of flake8 to be <3.9.2

0.2.6 (2020-03-21)

  • Set max supported version of flake8 to be <3.9.1

0.2.5 (2020-10-06)

  • Added official Python 3.9 support and tests

0.2.4 (2020-10-04)

  • Set max supported version of flake8 to be <3.8.5

0.2.3 (2020-10-02)

  • Fixed pre-commit hook file association so it support python and juypter notebooks

0.2.1 (2020-08-11)

  • Forced uft8 encoding when reading notebooks, this prevents errors on windows when console codepage is assumed

0.2.0 (2020-07-18)

  • Added pre-commit hook (#47)

0.1.8 (2020-06-09)

  • Set max supported version of flake8 to be <=3.8.3

0.1.7 (2020-05-25)

  • Set max supported version of flake8 to be <=3.8.2

0.1.6 (2020-05-20)

  • Set max supported version of flake8 to be <=3.8.1

  • Fixed bug with --exclude option

0.1.4 (2020-01-01)

  • Set max supported version of flake8 to be <3.8.0, to prevent breaking due to changes of flake8’s inner workings.

0.1.3 (2019-11-13)

  • Added official Python 3.8 support and tests

0.1.2 (2019-10-29)

  • Fixed compatibility with flake8==3.7.9

0.1.1 (2019-10-24)

  • Added console-script ‘flake8-nb’ as an alias for ‘flake8_nb’

0.1.0 (2019-10-22)

  • First release on PyPI.

Indices and tables