Skip to main content

Jupyter notebook linter for hidden-state and execution-order bugs.

Project description

nborder

A fast, opinionated linter and auto-fixer for Jupyter notebook hidden-state and execution-order bugs.

PyPI version CI Python License: MIT

What this catches

Code Name One-line example
NB101 Non-monotonic execution counts Cell 1 ran with In [3]: after cell 0 ran with In [5]:.
NB102 Won't survive Restart-and-Run-All print(df) references a name no cell in the notebook defines.
NB201 Use-before-assign across cells Cell 0 uses df; df = ... only appears in cell 1.
NB103 Stochastic library used without seed np.random.rand(3) runs with no seed call before it.

Each rule has a docs page under docs/rules/ explaining the bug class, a bad and good example, and the auto-fix behaviour.

Quick start

pip install nborder
nborder check notebook.ipynb
nborder check --fix notebook.ipynb
nborder check --output-format=json notebook.ipynb

The --fix flag reorders cells topologically when the dependency graph is a DAG, injects library-appropriate seed calls for stochastic libraries, and clears execution counts when they no longer reflect a reproducible run order. Every fix is a pipeline stage with a bailed outcome that does not block other fixes; running the same fix twice is a byte-stable no-op.

Pre-commit

Add this to your .pre-commit-config.yaml:

repos:
  - repo: https://github.com/moonrunnerkc/nborder
    rev: v0.1.0
    hooks:
      - id: nborder

Then pre-commit install. Full setup notes in docs/integrations/pre-commit.md.

GitHub Actions

- uses: moonrunnerkc/nborder@v0.1.0
  with:
    path: notebooks/

Diagnostics show up as inline annotations on the PR. Full options in docs/integrations/github-actions.md.

Configuration

nborder reads its configuration from [tool.nborder] in pyproject.toml:

[tool.nborder.seeds]
value = 42
libraries = ["numpy", "torch", "tensorflow", "random"]

Run nborder config to print the effective merged configuration.

FAQ

Why not use ruff? Ruff lints Python source, not notebook structure. It does not see cross-cell dataflow, so it cannot detect that df is used in cell 0 and only defined in cell 1. nborder is purpose-built for the cross-cell story; it is complementary to ruff, not competitive.

How is this different from nbqa? nbqa runs Python linters against notebook cells one at a time. nborder builds a cross-cell symbol dependency graph and reasons about the relationships between cells, which is the part nbqa explicitly does not do.

Does it work with R or Julia notebooks? Not in v0.1. Multi-language support is reserved for a future release. Python kernels cover roughly 95% of notebooks in the wild.

Will it modify my notebook outputs? No. Outputs, cell metadata, and notebook-level metadata are read-only. The only fix that touches execution_count is a clear-to-null operation that runs as part of the reorder fix.

What about magics? %line, %%cell, !shell, and shell-assignment forms (files = !ls) are stripped to typed metadata before parsing. Magic-defined bindings (e.g., %%capture out defines out) are recorded in the dataflow graph; see docs/known-limitations.md for the limits.

How do I suppress a false positive? Add # nborder: noqa (suppress all rules in the cell) or # nborder: noqa: NB201,NB102 (suppress specific rules) to any line in the cell.

What if I want to disable a rule entirely? Use the select and ignore fields in [tool.nborder] to drop a rule code from the enabled set.

Contributing

See CONTRIBUTING.md.

License

MIT. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nborder-0.1.0.tar.gz (44.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nborder-0.1.0-py3-none-any.whl (41.6 kB view details)

Uploaded Python 3

File details

Details for the file nborder-0.1.0.tar.gz.

File metadata

  • Download URL: nborder-0.1.0.tar.gz
  • Upload date:
  • Size: 44.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for nborder-0.1.0.tar.gz
Algorithm Hash digest
SHA256 046a2968be7536c69e1464732dfcc0d49d4d3508c6eaaa2e30c5a02e6cf3c35f
MD5 70d243bfd4dbefb5eaac328210206a65
BLAKE2b-256 58472f81441c5ffabfed897ff4afb2cbb45487f0e3792ecb01944ff99802a8f7

See more details on using hashes here.

File details

Details for the file nborder-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: nborder-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 41.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for nborder-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f152a61edb4e6f569dc4b6016c4ae4db5e2b0cc806fa5c3be674271ea5c12b6a
MD5 e5fbd7c3402a0438b77559c951597d2b
BLAKE2b-256 e1426fec134bdbfe0a6288c408ec183a72448c68341372ae4e7376f69d2b78d2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page