pax_global_header00006660000000000000000000000064144527540300014516gustar00rootroot0000000000000052 comment=4c265b76f7d445770f117334fc83874b9946f538 nbformat-5.9.1/000077500000000000000000000000001445275403000133425ustar00rootroot00000000000000nbformat-5.9.1/.git-blame-ignore-revs000066400000000000000000000001071445275403000174400ustar00rootroot00000000000000# Initial pre-commit reformat e4067d87e1728bfd2219adbbe6ba18b4b8061cab nbformat-5.9.1/.github/000077500000000000000000000000001445275403000147025ustar00rootroot00000000000000nbformat-5.9.1/.github/dependabot.yml000066400000000000000000000003151445275403000175310ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" - package-ecosystem: "pip" directory: "/" schedule: interval: "weekly" nbformat-5.9.1/.github/scripts/000077500000000000000000000000001445275403000163715ustar00rootroot00000000000000nbformat-5.9.1/.github/scripts/create_npmrc.py000066400000000000000000000007731445275403000214140ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. # Standard library imports import os def create_npmrc(): """ Create NPM configuration file in user home directory to use authentication token from environment variables. """ fpath = os.path.expanduser("~/.npmrc") with open(fpath, "w") as fh: fh.write("//registry.npmjs.org/:_authToken=${NPM_TOKEN}") if __name__ == "__main__": create_npmrc() nbformat-5.9.1/.github/scripts/parse_ref.py000066400000000000000000000015031445275403000207100ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. # Standard library imports import os # Constants HERE = os.path.abspath(os.path.dirname(__file__)) REPO_ROOT = os.path.dirname(os.path.dirname(HERE)) def parse_ref(current_ref): """ Extract version string from github reference string and create environment variable for use within the CI workflows. Parameters ---------- current_ref: str The github reference string. """ if not current_ref.startswith("refs/tags/"): raise Exception(f"Invalid ref `{current_ref}`!") # noqa tag_name = current_ref.replace("refs/tags/", "") print(tag_name) # noqa if __name__ == "__main__": current_ref = os.environ.get("GITHUB_REF") parse_ref(current_ref) nbformat-5.9.1/.github/workflows/000077500000000000000000000000001445275403000167375ustar00rootroot00000000000000nbformat-5.9.1/.github/workflows/enforce-label.yml000066400000000000000000000005001445275403000221530ustar00rootroot00000000000000name: Enforce PR label on: pull_request: types: [labeled, unlabeled, opened, edited, synchronize] jobs: enforce-label: runs-on: ubuntu-latest permissions: pull-requests: write steps: - name: enforce-triage-label uses: jupyterlab/maintainer-tools/.github/actions/enforce-label@v1 nbformat-5.9.1/.github/workflows/prep-release.yml000066400000000000000000000026571445275403000220600ustar00rootroot00000000000000name: "Step 1: Prep Release" on: workflow_dispatch: inputs: version_spec: description: "New Version Specifier" default: "next" required: false branch: description: "The branch to target" required: false post_version_spec: description: "Post Version Specifier" required: false since: description: "Use PRs with activity since this date or git reference" required: false since_last_stable: description: "Use PRs with activity since the last stable git tag" required: false type: boolean jobs: prep_release: runs-on: ubuntu-latest steps: - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - name: Prep Release id: prep-release uses: jupyter-server/jupyter_releaser/.github/actions/prep-release@v2 with: token: ${{ secrets.ADMIN_GITHUB_TOKEN }} version_spec: ${{ github.event.inputs.version_spec }} post_version_spec: ${{ github.event.inputs.post_version_spec }} target: ${{ github.event.inputs.target }} branch: ${{ github.event.inputs.branch }} since: ${{ github.event.inputs.since }} since_last_stable: ${{ github.event.inputs.since_last_stable }} - name: "** Next Step **" run: | echo "Optional): Review Draft Release: ${{ steps.prep-release.outputs.release_url }}" nbformat-5.9.1/.github/workflows/publish-release.yml000066400000000000000000000034761445275403000225600ustar00rootroot00000000000000name: "Step 2: Publish Release" on: workflow_dispatch: inputs: branch: description: "The target branch" required: false release_url: description: "The URL of the draft GitHub release" required: false steps_to_skip: description: "Comma separated list of steps to skip" required: false jobs: publish_release: runs-on: ubuntu-latest steps: - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - name: Populate Release id: populate-release uses: jupyter-server/jupyter_releaser/.github/actions/populate-release@v2 with: token: ${{ secrets.ADMIN_GITHUB_TOKEN }} target: ${{ github.event.inputs.target }} branch: ${{ github.event.inputs.branch }} release_url: ${{ github.event.inputs.release_url }} steps_to_skip: ${{ github.event.inputs.steps_to_skip }} - name: Finalize Release id: finalize-release env: PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} PYPI_TOKEN_MAP: ${{ secrets.PYPI_TOKEN_MAP }} TWINE_USERNAME: __token__ NPM_TOKEN: ${{ secrets.NPM_TOKEN }} uses: jupyter-server/jupyter-releaser/.github/actions/finalize-release@v2 with: token: ${{ secrets.ADMIN_GITHUB_TOKEN }} target: ${{ github.event.inputs.target }} release_url: ${{ steps.populate-release.outputs.release_url }} - name: "** Next Step **" if: ${{ success() }} run: | echo "Verify the final release" echo ${{ steps.finalize-release.outputs.release_url }} - name: "** Failure Message **" if: ${{ failure() }} run: | echo "Failed to Publish the Draft Release Url:" echo ${{ steps.populate-release.outputs.release_url }} nbformat-5.9.1/.github/workflows/tests.yml000066400000000000000000000114461445275403000206320ustar00rootroot00000000000000name: Run tests on: push: branches: ["main"] pull_request: schedule: - cron: "0 8 * * *" defaults: run: shell: bash -eux {0} jobs: tests: runs-on: ${{ matrix.os }} timeout-minutes: 20 strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] python-version: ["3.8", "3.11"] include: - os: windows-latest python-version: "3.9" - os: ubuntu-latest python-version: "pypy-3.8" - os: ubuntu-latest python-version: "3.12.0-beta.1" - os: macos-latest python-version: "3.10" steps: - uses: actions/checkout@v3 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - name: Run the tests if: ${{ !startsWith(matrix.python-version, 'pypy') && !startsWith(matrix.os, 'windows') }} run: | hatch run cov:test --cov-fail-under 75 || hatch run test:test --lf - name: Run the tests on pypy if: ${{ startsWith(matrix.python-version, 'pypy') }} run: | hatch run test:nowarn || hatch run test:nowarn --lf - name: Run the tests on windows if: ${{ startsWith(matrix.os, 'windows') }} run: | hatch run cov:nowarn || hatch run test:nowarn --lf - run: hatch version 100.100.100 - uses: jupyterlab/maintainer-tools/.github/actions/upload-coverage@v1 coverage: runs-on: ubuntu-latest needs: - tests steps: - uses: actions/checkout@v3 - uses: jupyterlab/maintainer-tools/.github/actions/report-coverage@v1 with: fail_under: 77 test_lint: name: Test Lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - name: Run Linters run: | hatch run typing:test hatch run lint:style pipx run interrogate -v nbformat pipx run doc8 --max-line-length=200 docs: runs-on: windows-latest steps: - uses: actions/checkout@v3 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - name: Test docs run: hatch run docs:build test_minimum_versions: name: Test Minimum Versions timeout-minutes: 20 runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Base Setup uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 with: dependency_type: minimum - name: Run the unit tests run: | hatch run test:nowarn || hatch run test:nowarn --lf test_prereleases: name: Test Prereleases runs-on: ubuntu-latest timeout-minutes: 20 steps: - name: Checkout uses: actions/checkout@v3 - name: Base Setup uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 with: dependency_type: pre - name: Run the tests run: | hatch run test:nowarn || hatch run test:nowarn --lf make_sdist: name: Make SDist runs-on: ubuntu-latest timeout-minutes: 10 steps: - uses: actions/checkout@v3 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - uses: jupyterlab/maintainer-tools/.github/actions/make-sdist@v1 test_sdist: runs-on: ubuntu-latest needs: [make_sdist] name: Install from SDist and Test timeout-minutes: 20 steps: - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - uses: jupyterlab/maintainer-tools/.github/actions/test-sdist@v1 check_release: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Base Setup uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - name: Install Dependencies run: | pip install -e . - name: Check Release uses: jupyter-server/jupyter_releaser/.github/actions/check-release@v2 with: token: ${{ secrets.GITHUB_TOKEN }} check_links: name: Check Links runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@v3 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - uses: jupyterlab/maintainer-tools/.github/actions/check-links@v1 with: ignore_glob: "tests/*.ipynb" tests_check: # This job does nothing and is only used for the branch protection if: always() needs: - coverage - test_lint - docs - test_minimum_versions - test_prereleases - check_links - check_release - test_sdist runs-on: ubuntu-latest steps: - name: Decide whether the needed jobs succeeded or failed uses: re-actors/alls-green@release/v1 with: jobs: ${{ toJSON(needs) }} nbformat-5.9.1/.gitignore000066400000000000000000000002771445275403000153400ustar00rootroot00000000000000MANIFEST build dist _build docs/man/*.gz .cache *.py[co] __pycache__ *.egg-info *~ *.bak .ipynb_checkpoints .tox **.DS_Store \#*# .#* .coverage .cache .python-version .idea docs/CHANGELOG.md nbformat-5.9.1/.mailmap000066400000000000000000000250661445275403000147740ustar00rootroot00000000000000A. J. Holyoake ajholyoake Aaron Culich Aaron Culich Aron Ahmadia ahmadia Benjamin Ragan-Kelley Benjamin Ragan-Kelley Min RK Benjamin Ragan-Kelley MinRK Barry Wark Barry Wark Ben Edwards Ben Edwards Bradley M. Froehle Bradley M. Froehle Bradley M. Froehle Bradley Froehle Brandon Parsons Brandon Parsons Brian E. Granger Brian Granger Brian E. Granger Brian Granger <> Brian E. Granger bgranger <> Brian E. Granger bgranger Christoph Gohlke cgohlke Cyrille Rossant rossant Damián Avila damianavila Damián Avila damianavila Damon Allen damontallen Darren Dale darren.dale <> Darren Dale Darren Dale <> Dav Clark Dav Clark <> Dav Clark Dav Clark David Hirschfeld dhirschfeld David P. Sanders David P. Sanders David Warde-Farley David Warde-Farley <> Doug Blank Doug Blank Eugene Van den Bulke Eugene Van den Bulke Evan Patterson Evan Patterson Evan Patterson Evan Patterson Evan Patterson epatters Evan Patterson epatters Ernie French Ernie French Ernie French ernie french Ernie French ernop Fernando Perez Fernando Perez Fernando Perez Fernando Perez fperez <> Fernando Perez fptest <> Fernando Perez fptest1 <> Fernando Perez Fernando Perez Fernando Perez Fernando Perez <> Fernando Perez Fernando Perez Frank Murphy Frank Murphy Gabriel Becker gmbecker Gael Varoquaux gael.varoquaux <> Gael Varoquaux gvaroquaux Gael Varoquaux Gael Varoquaux <> Ingolf Becker watercrossing Jake Vanderplas Jake Vanderplas Jakob Gager jakobgager Jakob Gager jakobgager Jakob Gager jakobgager Jason Grout Jason Grout Jason Gors jason gors Jason Gors jgors Jens Hedegaard Nielsen Jens Hedegaard Nielsen Jens Hedegaard Nielsen Jens H Nielsen Jens Hedegaard Nielsen Jens H. Nielsen Jez Ng Jez Ng Jonathan Frederic Jonathan Frederic Jonathan Frederic Jonathan Frederic Jonathan Frederic Jonathan Frederic Jonathan Frederic jon Jonathan Frederic U-Jon-PC\Jon Jonathan March Jonathan March Jonathan March jdmarch Jörgen Stenarson Jörgen Stenarson Jörgen Stenarson Jorgen Stenarson Jörgen Stenarson Jorgen Stenarson <> Jörgen Stenarson jstenar Jörgen Stenarson jstenar <> Jörgen Stenarson Jörgen Stenarson Juergen Hasch juhasch Juergen Hasch juhasch Julia Evans Julia Evans Kester Tong KesterTong Kyle Kelley Kyle Kelley Kyle Kelley rgbkrk Laurent Dufréchou Laurent Dufréchou Laurent Dufréchou laurent dufrechou <> Laurent Dufréchou laurent.dufrechou <> Laurent Dufréchou Laurent Dufrechou <> Laurent Dufréchou laurent.dufrechou@gmail.com <> Laurent Dufréchou ldufrechou Lorena Pantano Lorena Luis Pedro Coelho Luis Pedro Coelho Marc Molla marcmolla Martín Gaitán Martín Gaitán Matthias Bussonnier Matthias BUSSONNIER Matthias Bussonnier Bussonnier Matthias Matthias Bussonnier Matthias BUSSONNIER Matthias Bussonnier Matthias Bussonnier Michael Droettboom Michael Droettboom Nicholas Bollweg Nicholas Bollweg (Nick) Nicolas Rougier Nikolay Koldunov Nikolay Koldunov Omar Andrés Zapata Mesa Omar Andres Zapata Mesa Omar Andrés Zapata Mesa Omar Andres Zapata Mesa Pankaj Pandey Pankaj Pandey Pascal Schetelat pascal-schetelat Paul Ivanov Paul Ivanov Pauli Virtanen Pauli Virtanen <> Pauli Virtanen Pauli Virtanen Pierre Gerold Pierre Gerold Pietro Berkes Pietro Berkes Piti Ongmongkolkul piti118 Prabhu Ramachandran Prabhu Ramachandran <> Puneeth Chaganti Puneeth Chaganti Robert Kern rkern <> Robert Kern Robert Kern Robert Kern Robert Kern Robert Kern Robert Kern <> Robert Marchman Robert Marchman Satrajit Ghosh Satrajit Ghosh Satrajit Ghosh Satrajit Ghosh Scott Sanderson Scott Sanderson smithj1 smithj1 smithj1 smithj1 Steven Johnson stevenJohnson Steven Silvester blink1073 S. Weber s8weber Stefan van der Walt Stefan van der Walt Silvia Vinyes Silvia Silvia Vinyes silviav12 Sylvain Corlay Sylvain Corlay sylvain.corlay Ted Drain TD22057 Théophile Studer Théophile Studer Thomas Kluyver Thomas Thomas Spura Thomas Spura Timo Paulssen timo vds vds2212 vds vds Ville M. Vainio Ville M. Vainio ville Ville M. Vainio ville Ville M. Vainio vivainio <> Ville M. Vainio Ville M. Vainio Ville M. Vainio Ville M. Vainio Walter Doerwald walter.doerwald <> Walter Doerwald Walter Doerwald <> W. Trevor King W. Trevor King Yoval P. y-p nbformat-5.9.1/.pre-commit-config.yaml000066400000000000000000000017311445275403000176250ustar00rootroot00000000000000ci: autoupdate_schedule: monthly repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.4.0 hooks: - id: check-case-conflict - id: check-ast - id: check-docstring-first - id: check-executables-have-shebangs - id: check-added-large-files - id: check-case-conflict - id: check-merge-conflict - id: check-json - id: check-toml - id: check-yaml - id: debug-statements - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema rev: 0.23.2 hooks: - id: check-github-workflows - repo: https://github.com/executablebooks/mdformat rev: 0.7.16 hooks: - id: mdformat - repo: https://github.com/psf/black rev: 23.3.0 hooks: - id: black - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.0.276 hooks: - id: ruff args: ["--fix"] exclude: script nbformat-5.9.1/.readthedocs.yaml000066400000000000000000000003541445275403000165730ustar00rootroot00000000000000version: 2 sphinx: configuration: docs/conf.py python: install: # install itself with pip install . - method: pip path: . extra_requirements: - docs build: os: ubuntu-22.04 tools: python: "3.11" nbformat-5.9.1/CHANGELOG.md000066400000000000000000000352631445275403000151640ustar00rootroot00000000000000(changelog)= # Changelog ## 5.9.1 ([Full Changelog](https://github.com/jupyter/nbformat/compare/v5.9.0...c348f9d12f05b4e0350413c74f58cd9e4f54a550)) ### Maintenance and upkeep improvements - Fix deprecation warning when importing from jsonschema [#368](https://github.com/jupyter/nbformat/pull/368) ([@eladkal](https://github.com/eladkal)) ### Contributors to this release ([GitHub contributors page for this release](https://github.com/jupyter/nbformat/graphs/contributors?from=2023-05-31&to=2023-07-10&type=c)) [@eladkal](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Aeladkal+updated%3A2023-05-31..2023-07-10&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Apre-commit-ci+updated%3A2023-05-31..2023-07-10&type=Issues) ## 5.9.0 ([Full Changelog](https://github.com/jupyter/nbformat/compare/v5.8.0...1b5e8e4e9af98f9c9b0843ba155b8756103d094d)) ### Maintenance and upkeep improvements - Support Python 3.12 [#363](https://github.com/jupyter/nbformat/pull/363) ([@blink1073](https://github.com/blink1073)) - Use local coverage [#360](https://github.com/jupyter/nbformat/pull/360) ([@blink1073](https://github.com/blink1073)) - Bump actions/checkout from 2 to 3 [#350](https://github.com/jupyter/nbformat/pull/350) ([@dependabot](https://github.com/dependabot)) ### Contributors to this release ([GitHub contributors page for this release](https://github.com/jupyter/nbformat/graphs/contributors?from=2023-03-20&to=2023-05-31&type=c)) [@blink1073](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Ablink1073+updated%3A2023-03-20..2023-05-31&type=Issues) | [@dependabot](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Adependabot+updated%3A2023-03-20..2023-05-31&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Apre-commit-ci+updated%3A2023-03-20..2023-05-31&type=Issues) ## 5.8.0 ([Full Changelog](https://github.com/jupyter/nbformat/compare/v5.7.3...85917af9c77beae326531e1923e0ec47725e590b)) ### Enhancements made - Add strip_invalid_metadata argument to validator normalize method [#355](https://github.com/jupyter/nbformat/pull/355) ([@jonabc](https://github.com/jonabc)) ### Maintenance and upkeep improvements - Fix codecov badge [#352](https://github.com/jupyter/nbformat/pull/352) ([@blink1073](https://github.com/blink1073)) - Add license [#348](https://github.com/jupyter/nbformat/pull/348) ([@dcsaba89](https://github.com/dcsaba89)) - Add more linting [#345](https://github.com/jupyter/nbformat/pull/345) ([@blink1073](https://github.com/blink1073)) - Only add ellipsis to NotJSONError message if message is truncated [#344](https://github.com/jupyter/nbformat/pull/344) ([@rschroll](https://github.com/rschroll)) ### Documentation improvements - DOC: README: capitalization, title [#346](https://github.com/jupyter/nbformat/pull/346) ([@westurner](https://github.com/westurner)) ### Contributors to this release ([GitHub contributors page for this release](https://github.com/jupyter/nbformat/graphs/contributors?from=2023-01-12&to=2023-03-20&type=c)) [@blink1073](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Ablink1073+updated%3A2023-01-12..2023-03-20&type=Issues) | [@dcsaba89](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Adcsaba89+updated%3A2023-01-12..2023-03-20&type=Issues) | [@jonabc](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Ajonabc+updated%3A2023-01-12..2023-03-20&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Apre-commit-ci+updated%3A2023-01-12..2023-03-20&type=Issues) | [@rschroll](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Arschroll+updated%3A2023-01-12..2023-03-20&type=Issues) | [@westurner](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Awesturner+updated%3A2023-01-12..2023-03-20&type=Issues) ## 5.7.3 ([Full Changelog](https://github.com/jupyter/nbformat/compare/v5.7.2...1eefc29edff5da06f78c0087e7c06e644a6abcc9)) ### Maintenance and upkeep improvements - Undeprecate validate(nb, relax_add_props=True) [#343](https://github.com/jupyter/nbformat/pull/343) ([@minrk](https://github.com/minrk)) ### Contributors to this release ([GitHub contributors page for this release](https://github.com/jupyter/nbformat/graphs/contributors?from=2023-01-11&to=2023-01-12&type=c)) [@minrk](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Aminrk+updated%3A2023-01-11..2023-01-12&type=Issues) ## 5.7.2 ([Full Changelog](https://github.com/jupyter/nbformat/compare/v5.7.1...30f3d81e7113ad7628443fc4cd389ca16b2d186a)) ### Bugs fixed - Only require nbformat_minor for v4 [#342](https://github.com/jupyter/nbformat/pull/342) ([@minrk](https://github.com/minrk)) ### Maintenance and upkeep improvements - Fix check release [#341](https://github.com/jupyter/nbformat/pull/341) ([@blink1073](https://github.com/blink1073)) - Add spell checker and enforce docstrings [#339](https://github.com/jupyter/nbformat/pull/339) ([@blink1073](https://github.com/blink1073)) - Fix docs build [#338](https://github.com/jupyter/nbformat/pull/338) ([@blink1073](https://github.com/blink1073)) ### Contributors to this release ([GitHub contributors page for this release](https://github.com/jupyter/nbformat/graphs/contributors?from=2022-12-19&to=2023-01-11&type=c)) [@blink1073](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Ablink1073+updated%3A2022-12-19..2023-01-11&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Aminrk+updated%3A2022-12-19..2023-01-11&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Apre-commit-ci+updated%3A2022-12-19..2023-01-11&type=Issues) ## 5.7.1 ([Full Changelog](https://github.com/jupyter/nbformat/compare/5.7.0...45ff0cd6dbc5e46a3b620124deeda00aaeebfa29)) ### Maintenance and upkeep improvements - Expose more attributes for typing [#337](https://github.com/jupyter/nbformat/pull/337) ([@blink1073](https://github.com/blink1073)) - Fix lint [#336](https://github.com/jupyter/nbformat/pull/336) ([@blink1073](https://github.com/blink1073)) - Adopt ruff and address lint [#333](https://github.com/jupyter/nbformat/pull/333) ([@blink1073](https://github.com/blink1073)) - Use base setup dependency type [#329](https://github.com/jupyter/nbformat/pull/329) ([@blink1073](https://github.com/blink1073)) - Switch to using Jupyter Releaser [#326](https://github.com/jupyter/nbformat/pull/326) ([@blink1073](https://github.com/blink1073)) - More maintenance cleanup [#325](https://github.com/jupyter/nbformat/pull/325) ([@blink1073](https://github.com/blink1073)) - Handle warning from jupyter client [#322](https://github.com/jupyter/nbformat/pull/322) ([@blink1073](https://github.com/blink1073)) - Add dependabot [#320](https://github.com/jupyter/nbformat/pull/320) ([@blink1073](https://github.com/blink1073)) - Clean up docs and maintenance [#314](https://github.com/jupyter/nbformat/pull/314) ([@blink1073](https://github.com/blink1073)) ### Documentation improvements - Fix changelog target [#321](https://github.com/jupyter/nbformat/pull/321) ([@chrisjsewell](https://github.com/chrisjsewell)) - Clean up docs and maintenance [#314](https://github.com/jupyter/nbformat/pull/314) ([@blink1073](https://github.com/blink1073)) ### Other merged PRs ### Contributors to this release ([GitHub contributors page for this release](https://github.com/jupyter/nbformat/graphs/contributors?from=2022-10-10&to=2022-12-19&type=c)) [@blink1073](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Ablink1073+updated%3A2022-10-10..2022-12-19&type=Issues) | [@chrisjsewell](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Achrisjsewell+updated%3A2022-10-10..2022-12-19&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyter%2Fnbformat+involves%3Apre-commit-ci+updated%3A2022-10-10..2022-12-19&type=Issues) # Changes in nbformat ## 5.7.0 - Always use jsonschema to handle error reporting. - Fix deprecation warning suggestion. ## 5.6.1 - Fix handling of `__version__` on Python 3.7. ## 5.6.0 - Fix docs and type annotations for `validator.normalize`. - Switch to hatch build backend. ## 5.5.0 The biggest change in `nbformat` 5.5.0 is the deprecation of arguments to `validate()` that try to fix notebooks errors during validation. `validate()` is a function that is core to the security model of Jupyter, and is assumed in a number of places to not mutate it's argument, or try to fix notebooks passed to it. Auto fixing of notebook in validate can also hide subtle bugs, and will therefore be updated in a near future to not take any of the argument related to auto-fixing, and fail instead of silently modifying its parameters on invalid notebooks. `nbformat` now contain a `normalize` function that will return a normalized copy of a notebook that is suitable for validation. While offered as a convenience we discourage its use and suggest library make sure to generate valid notebooks. ### Other changes - `nbformat` is now built with flit, and uses `pyproject.toml` - Documentation and Deprecations have been updated with version number and stack levels. ## 5.4.0 - Add project URLs to `setup.py` - Fix import in `nbformat.current` - Add `mypy` and typings support - Improve CI ## 5.3.0 - Use `fastjsonschema` by default - Adopt `pre-commit` and auto-formatters - Increase minimum `jsonschema` to 2.6, handle warnings ## 5.2.0 - Add ability to capture validation errors - Update supported python versions - Ensure nbformat minor version is present when upgrading - Only fix cell ID validation issues if asked - Return the notebook when no conversion is needed - Catch AttributeErrors stemming from ipython_genutils as ValidationErrors on read - Don't list pytest-cov as a test dependency - Remove dependency on IPython genutils - Include tests in sdist but not wheel ## 5.1.3 - Change id generation to be hash based to avoid problematic word combinations - Added tests for python 3.9 - Fixed setup.py build operations to include package data ## 5.1.2 - Fixed missing file in manifest ## 5.1.1 - Changes convert.upgrade to upgrade minor 4.x versions to 4.5 ## 5.1.0 - Implemented CellIds from JEP-62 - Fixed a regression introduced when using fastjsonschema, which does not directly support to validate a "reference"/"subschema" - Removed unreachable/unneeded code - Added CI workflow for package release on tag push ## 5.0.8 - Add optional support for using \[fastjsonschema\]{.title-ref} as the JSON validation library. To enable fast validation, install \[fastjsonschema\]{.title-ref} and set the environment variable \[NBFORMAT_VALIDATOR\]{.title-ref} to the value \[fastjsonschema\]{.title-ref}. ## 5.0.7 - Fixed a bug where default values for validator.get_validator() failed with an import error ## 5.0.6 - nbformat.read() function has a better duck-type interface and will raise more meaningful error messages if it can't parse a notebook document. ## 5.0.5 - Allow notebook format 4.0 and 4.1 to have the arbitrary JSON mimebundles from format 4.2 for pragmatic purposes. - Support reading/writing path-like objects has been added to read operations. ## 5.0.4 - Fixed issue causing python 2 to pick up 5.0.x releases. ## 5.0.3 - Removed debug print statements from project. ## 5.0.2 - Added schema validation files for older versions. This was breaking notebook generation. ## 5.0.1 ## 5.0 [5.0 on GitHub](https://github.com/jupyter/nbformat/milestone/5) - Starting with 5.0, `nbformat` is now Python 3 only (>= 3.5) - Add execution timings in code cell metadata for v4 spec. `"metadata": { "execution": {...}}` should be populated with kernel-specific timing information. - Documentation for how markup is used in notebooks added - Link to json schema docs from format page added - Documented the editable metadata flag - Update description for collapsed field - Documented notebook format versions 4.0-4.3 with accurate json schema specification files - Clarified info about name's meaning for cells - Added a default execution_count of None for new_output_cell('execute_result') - Added support for handling nbjson kwargs - Wheels now correctly have a LICENSE file - Travis builds now have a few more execution environments ## 4.4 [4.4 on GitHub](https://github.com/jupyter/nbformat/milestone/9) - Explicitly state that metadata fields can be ignored. - Introduce official jupyter namespace inside metadata (`metadata.jupyter`). - Introduce `source_hidden` and `outputs_hidden` as official front-end metadata fields to indicate hiding source and outputs areas. **NB**: These fields should not be used to hide elements in exported formats. - Fix ending the redundant storage of signatures in the signature database. - `nbformat.validate` can be set to not raise a ValidationError if additional properties are included. - Fix for errors with connecting and backing up the signature database. - Dict-like objects added to NotebookNode attributes are now transformed to be NotebookNode objects; transformation also works for \[.update()\]{.title-ref}. ## 4.3 [4.3 on GitHub](https://github.com/jupyter/nbformat/milestone/7) - A new pluggable `SignatureStore` class allows specifying different ways to record the signatures of trusted notebooks. The default is still an SQLite database. See `pluggable_signature_store` for more information. - `nbformat.read` and `nbformat.write` accept file paths as bytes as well as unicode. - Fix for calling `nbformat.validate` on an empty dictionary. - Fix for running the tests where the locale makes ASCII the default encoding. - Include nbformat-schema files (v3 and v4) in nbformat-schema npm package. - Include configuration for appveyor's continuous integration service. ## 4.2 ### 4.2.0 [4.2 on GitHub](https://github.com/jupyter/nbformat/milestones/4.2) - Update nbformat spec version to 4.2, allowing JSON outputs to have any JSONable type, not just `object`, and mime-types of the form `application/anything+json`. - Define basics of `authors` in notebook metadata. `nb.metadata.authors` shall be a list of objects with the property `name`, a string of each author's full name. - Update use of traitlets API to require traitlets 4.1. - Support trusting notebooks on stdin with `cat notebook | jupyter trust` ## 4.1 ### 4.1.0 [4.1 on GitHub](https://github.com/jupyter/nbformat/milestones/4.1) - Update nbformat spec version to 4.1, adding support for attachments on markdown and raw cells. - Catch errors opening trust database, falling back on `:memory:` if the database cannot be opened. ## 4.0 [4.0 on GitHub](https://github.com/jupyter/nbformat/milestones/4.0) The first release of nbformat as its own package. nbformat-5.9.1/CONTRIBUTING.md000066400000000000000000000047161445275403000156030ustar00rootroot00000000000000# Contributing We follow the [IPython Contributing Guide](https://github.com/ipython/ipython/blob/master/CONTRIBUTING.md). ## Code Styling `nbformat` has adopted automatic code formatting so you shouldn't need to worry too much about your code style. As long as your code is valid, the pre-commit hook should take care of how it should look. You can invoke the pre-commit hook by hand at any time with: ```bash pre-commit run ``` which should run any autoformatting on your code and tell you about any errors it couldn't fix automatically. You may also install [black integration](https://black.readthedocs.io/en/stable/integrations/editors.html) into your text editor to format code automatically. If you have already committed files before setting up the pre-commit hook with `pre-commit install`, you can fix everything up using `pre-commit run --all-files`. You need to make the fixing commit yourself after that. Some of the hooks only run on CI by default, but you can invoke them by running with the `--hook-stage manual` argument. ## Release guidelines The nbformat version will change in a package release only when there are material changes in the specification itself. This Python package can be released with no spec changes. For example, the package version may be bumped to 5.0 to drop Python 2 support with no changes in the nbformat spec number. When this package is released, if there are material changes in the specification, update the appropriate schema file to reflect the new version (both in its top-level description and in its minimum minor/major version numbers in the spec) and copy the file to an archived schema for that particular version. Update the minor format for tests as well. For example, for nbformat package version 4.5, if we see that there are material changes in the spec, so do the following: - Update `nbformat/v4/nbformat.v4.schema.json` so that its top-level description says spec version 4.4 (which is the next spec version), and its minimum minor version number is 4 in the schema. - Copy `nbformat/v4/nbformat.v4.schema.json` to `nbformat/v4/nbformat.v4.4.schema.json` and commit the file as an archived version of that particular nbformat specification. - Update the `nbformat` and `nbformat_minor` variables in `nbformat/v4/nbbase.py` If there are inconsequential changes to the format spec in a package release (such as fixing a typo in the documentation of a field), just update the archived spec file when the package is released. nbformat-5.9.1/LICENSE000066400000000000000000000030641445275403000143520ustar00rootroot00000000000000BSD 3-Clause License - Copyright (c) 2001-2015, IPython Development Team - Copyright (c) 2015-, Jupyter Development Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nbformat-5.9.1/README.md000066400000000000000000000043771445275403000146340ustar00rootroot00000000000000# nbformat: Jupyter Notebook Format ![CI Tests](https://github.com/jupyter/nbformat/workflows/Run%20tests/badge.svg) `nbformat` contains the reference implementation of the [Jupyter Notebook format], and Python APIs for working with notebooks. There is also a JSON Schema for nbformat versions >= 3. ## Installation From the command line: ```{.sourceCode .bash} pip install nbformat ``` ## Using a different json schema validator We use `fastjsonschema` by default. To use `jsonschema` instead, set the environment variable `NBFORMAT_VALIDATOR` to the value `jsonschema`. ## Python Version Support This library supported Python 2.7 and Python 3.5+ for `4.x.x` releases. With Python 2's end-of-life nbformat `5.x.x` supported Python 3 only. Support for Python 3.x versions will be dropped when they are officially sunset by the python organization. ## Contributing Read [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines on how to setup a local development environment and make code changes back to nbformat. ## About the Jupyter Development Team The Jupyter Development Team is the set of all contributors to the Jupyter project. This includes all of the Jupyter subprojects. The core team that coordinates development on GitHub can be found here: https://github.com/jupyter/. ## Our Copyright Policy Jupyter uses a shared copyright model. Each contributor maintains copyright over their contributions to Jupyter. But, it is important to note that these contributions are typically only changes to the repositories. Thus, the Jupyter source code, in its entirety is not the copyright of any single person or institution. Instead, it is the collective copyright of the entire Jupyter Development Team. If individual contributors want to maintain a record of what changes/contributions they have specific copyright on, they should indicate their copyright in the commit message of the change, when they commit the change to one of the Jupyter repositories. With this in mind, the following banner should be used in any source code file to indicate the copyright and license terms: ``` # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. ``` [jupyter notebook format]: https://nbformat.readthedocs.org/en/latest/format_description.html nbformat-5.9.1/RELEASING.md000066400000000000000000000037351445275403000152050ustar00rootroot00000000000000# Releasing ## Prerequisites - If you have a schema version change, you need to bump the schema version manually: First copy `nbformat/v4/nbformat/.v4.schema.json` to `nbformat/v4/nbformat/.v4.schema.json`. Then edit the top of `nbformat/v4/nbbase.py`: ```python # Change the nbformat_minor and nbformat_schema variables when incrementing the # nbformat version # current major version nbformat = 4 # current minor version nbformat_minor = # schema files for (major, minor) version tuples. (None, None) means the current version nbformat_schema = { (None, None): 'nbformat.v4.schema.json', (4, 0): 'nbformat.v4.0.schema.json', ... (4, ): 'nbformat.v4..schema.json' } ``` If you do one of these steps but not the others it will fail many tests. ## Automated Release The recommended way to make a release is to use [`jupyter_releaser`](https://github.com/jupyter-server/jupyter_releaser) from this repository. - Run the "Step 1: Prep Release" workflow with the appropriate inputs. - Review the changelog in the draft GitHub release created in Step 1. ## Manual Release We use [hatch](https://hatch.pypa.io/latest/version/) to manage versions. You must first install `pipx` (or install `hatch` itself if you prefer). To bump versions we use the `pipx run hatch version ` command. ### To make a release ```bash # Commit, test, publish, beta tag pipx run hatch version git tag -a -m "" git push upstream master git push upstream --tags ``` ### Push to PyPI ```bash rm -rf dist/* rm -rf build/* pipx run build . # Double check the dist/* files have the right verison (no `.dev`) and install the wheel to ensure it's good pip install dist/* pipx run twine upload dist/* ``` ### Push to npm ```bash npm publish ``` Note for JavaScript developers -- `hatch` updates the version in `package.json`. nbformat-5.9.1/docs/000077500000000000000000000000001445275403000142725ustar00rootroot00000000000000nbformat-5.9.1/docs/Makefile000066400000000000000000000163711445275403000157420ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # User-friendly check for sphinx-build ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) endif # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " applehelp to make an Apple Help Book" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " xml to make Docutils-native XML files" @echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" @echo " coverage to run coverage check of the documentation (if enabled)" clean: rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/nbformat.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/nbformat.qhc" applehelp: $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp @echo @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." @echo "N.B. You won't be able to view it unless you put it in" \ "~/Library/Documentation/Help or install it in your application" \ "bundle." devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/nbformat" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/nbformat" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." latexpdfja: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through platex and dvipdfmx..." $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." coverage: $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage @echo "Testing of coverage in the sources finished, look at the " \ "results in $(BUILDDIR)/coverage/python.txt." xml: $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml @echo @echo "Build finished. The XML files are in $(BUILDDIR)/xml." pseudoxml: $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml @echo @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." nbformat-5.9.1/docs/api.rst000066400000000000000000000055701445275403000156040ustar00rootroot00000000000000Python API for working with notebook files ========================================== .. module:: nbformat Reading and writing ------------------- .. autofunction:: read .. autofunction:: reads The reading functions require you to pass the *as_version* parameter. Your code should specify the notebook format that it knows how to work with: for instance, if your code handles version 4 notebooks:: nb = nbformat.read('path/to/notebook.ipynb', as_version=4) This will automatically upgrade or downgrade notebooks in other versions of the notebook format to the structure your code knows about. .. autofunction:: write .. autofunction:: writes .. data:: NO_CONVERT This special value can be passed to the reading and writing functions, to indicate that the notebook should be loaded/saved in the format it's supplied. .. data:: current_nbformat current_nbformat_minor These integers represent the current notebook format version that the nbformat module knows about. NotebookNode objects -------------------- The functions in this module work with :class:`NotebookNode` objects, which are like dictionaries, but allow attribute access (``nb.cells``). The structure of these objects matches the notebook format described in :doc:`format_description`. .. autoclass:: NotebookNode .. autofunction:: from_dict Other functions --------------- .. autofunction:: convert .. autofunction:: validate .. autoclass:: ValidationError Constructing notebooks programmatically --------------------------------------- .. module:: nbformat.v4 These functions return :class:`~.NotebookNode` objects with the necessary fields. .. autofunction:: new_notebook .. autofunction:: new_code_cell .. autofunction:: new_markdown_cell .. autofunction:: new_raw_cell .. autofunction:: new_output .. autofunction:: output_from_msg Notebook signatures ------------------- .. module:: nbformat.sign This machinery is used by the notebook web application to record which notebooks are *trusted*, and may show dynamic output as soon as they're loaded. See :ref:`notebook:notebook_security` for more information. .. autoclass:: NotebookNotary .. automethod:: sign .. automethod:: unsign .. automethod:: check_signature .. automethod:: mark_cells .. automethod:: check_cells .. _pluggable_signature_store: Signature storage ***************** Signatures are stored using a pluggable :class:`SignatureStore` subclass. To implement your own, override the methods below and configure ``NotebookNotary.store_factory``. .. autoclass:: SignatureStore .. automethod:: store_signature .. automethod:: remove_signature .. automethod:: check_signature .. automethod:: close By default, :class:`NotebookNotary` will use an SQLite based store if SQLite bindings are available, and an in-memory store otherwise. .. autoclass:: SQLiteSignatureStore .. autoclass:: MemorySignatureStore nbformat-5.9.1/docs/conf.py000066400000000000000000000236121445275403000155750ustar00rootroot00000000000000#!/usr/bin/env python3 # # nbformat documentation build configuration file, created by # sphinx-quickstart on Thu May 14 17:26:52 2015. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) import os import shutil from importlib.metadata import version as get_version HERE = os.path.abspath(os.path.dirname(__file__)) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ "myst_parser", "sphinx.ext.autodoc", "sphinx.ext.intersphinx", "sphinx.ext.napoleon", ] try: import enchant # type:ignore # noqa extensions += ["sphinxcontrib.spelling"] except ImportError: pass # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # source_suffix = ['.rst', '.md'] source_suffix = ".rst" # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = "index" # General information about the project. project = "nbformat" copyright = "2015, Jupyter Development Team" # noqa author = "Jupyter Development Team" # numpydoc configuration numpydoc_show_class_members = False # Otherwise Sphinx emits thousands of warnings numpydoc_class_members_toctree = False # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = ".".join(get_version("nbformat").split(".")[:2]) # The full version, including alpha/beta/rc tags. release = version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = "en" # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ["_build"] # The reST default role (used for this markup: `text`) to use for all # documents. # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. # keep_warnings = False # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = "pydata_sphinx_theme" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". # html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. # html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Language to be used for generating the HTML full-text search index. # Sphinx supports the following languages: # 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' # 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr' # html_search_language = 'en' # A dictionary with options for the search language support, empty by default. # Now only 'ja' uses this config value # html_search_options = {'type': 'default'} # The name of a javascript file (relative to the configuration directory) that # implements a search results scorer. If empty, the default will be used. # html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. htmlhelp_basename = "nbformatdoc" # -- Options for LaTeX output --------------------------------------------- # latex_elements = {} # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ ( master_doc, "nbformat.tex", "nbformat Documentation", "Jupyter Development Team", "manual", ), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # If true, show page references after internal links. # latex_show_pagerefs = False # If true, show URL addresses after external links. # latex_show_urls = False # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [(master_doc, "nbformat", "nbformat Documentation", [author], 1)] # If true, show URL addresses after external links. # man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ( master_doc, "nbformat", "nbformat Documentation", author, "nbformat", "One line description of project.", "Miscellaneous", ), ] # Documents to append as an appendix to all manuals. # texinfo_appendices = [] # If false, no module index is generated. # texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. # texinfo_no_detailmenu = False # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = { "python": ("https://docs.python.org/3", None), "jupyterclient": ("https://jupyter-client.readthedocs.io/en/stable", None), "nbconvert": ("https://nbconvert.readthedocs.org/en/stable", None), "notebook": ("https://jupyter-notebook.readthedocs.org/en/stable", None), } def setup(_): dest = os.path.join(HERE, "changelog.md") shutil.copy(os.path.join(HERE, "..", "CHANGELOG.md"), dest) nbformat-5.9.1/docs/format_description.rst000066400000000000000000000355521445275403000207310ustar00rootroot00000000000000.. _notebook_file_format: ======================== The Notebook file format ======================== The official Jupyter Notebook format is defined with `this JSON schema `_, which is used by Jupyter tools to validate notebooks. This page contains a human-readable description of the notebook format. .. note:: *All* metadata fields are optional. While the types and values of some metadata fields are defined, no metadata fields are required to be defined. Any metadata field may also be ignored. Top-level structure =================== At the highest level, a Jupyter notebook is a dictionary with a few keys: - metadata (dict) - nbformat (int) - nbformat_minor (int) - cells (list) .. sourcecode:: python { "metadata" : { "kernel_info": { # if kernel_info is defined, its name field is required. "name" : "the name of the kernel" }, "language_info": { # if language_info is defined, its name field is required. "name" : "the programming language of the kernel", "version": "the version of the language", "codemirror_mode": "The name of the codemirror mode to use [optional]" } }, "nbformat": 4, "nbformat_minor": 0, "cells" : [ # list of cell dictionaries, see below ], } Some fields, such as code input and text output, are characteristically multi-line strings. When these fields are written to disk, they **may** be written as a list of strings, which should be joined with ``''`` when reading back into memory. In programmatic APIs for working with notebooks (Python, Javascript), these are always re-joined into the original multi-line string. If you intend to work with notebook files directly, you must allow multi-line string fields to be either a string or list of strings. Cell Types ========== There are a few basic cell types for encapsulating code and text. All cells have the following basic structure: .. sourcecode:: python { "cell_type" : "type", "metadata" : {}, "source" : "single string or [list, of, strings]", } .. note:: On disk, multi-line strings **MAY** be split into lists of strings. When read with the nbformat Python API, these multi-line strings will always be a single string. Markdown cells -------------- Markdown cells are used for body-text, and contain markdown, as defined in `GitHub-flavored markdown`_, and implemented in marked_. .. _GitHub-flavored markdown: https://help.github.com/articles/github-flavored-markdown .. _marked: https://github.com/chjj/marked .. sourcecode:: python { "cell_type" : "markdown", "metadata" : {}, "source" : "[multi-line *markdown*]", } .. versionchanged:: nbformat 4.0 Heading cells have been removed in favor of simple headings in markdown. Code cells ---------- Code cells are the primary content of Jupyter notebooks. They contain source code in the language of the document's associated kernel, and a list of outputs associated with executing that code. They also have an execution_count, which must be an integer or ``null``. .. sourcecode:: python { "cell_type" : "code", "execution_count": 1, # integer or null "metadata" : { "collapsed" : True, # whether the output of the cell is collapsed "scrolled": False, # any of true, false or "auto" }, "source" : "[some multi-line code]", "outputs": [{ # list of output dicts (described below) "output_type": "stream", ... }], } .. versionchanged:: nbformat 4.0 ``input`` was renamed to ``source``, for consistency among cell types. .. versionchanged:: nbformat 4.0 ``prompt_number`` renamed to ``execution_count`` Code cell outputs ----------------- A code cell can have a variety of outputs (stream data or rich mime-type output). These correspond to :ref:`messages ` produced as a result of executing the cell. All outputs have an ``output_type`` field, which is a string defining what type of output it is. stream output ************* .. sourcecode:: python { "output_type" : "stream", "name" : "stdout", # or stderr "text" : "[multiline stream text]", } .. versionchanged:: nbformat 4.0 The ``stream`` key was changed to ``name`` to match the stream message. .. _display-data: display_data ************ Rich display outputs, as created by ``display_data`` messages, contain data keyed by mime-type. This is often called a mime-bundle, and shows up in various locations in the notebook format and message spec. The metadata of these messages may be keyed by mime-type as well. .. sourcecode:: python { "output_type" : "display_data", "data" : { "text/plain" : "[multiline text data]", "image/png": "[base64-encoded-multiline-png-data]", "application/json": { # JSON data is included as-is "key1": "data", "key2": ["some", "values"], "key3": {"more": "data"} }, "application/vnd.exampleorg.type+json": { # JSON data, included as-is, when the mime-type key ends in +json "key1": "data", "key2": ["some", "values"], "key3": {"more": "data"} } }, "metadata" : { "image/png": { "width": 640, "height": 480, }, }, } .. versionchanged:: nbformat 4.0 ``application/json`` output is no longer double-serialized into a string. .. versionchanged:: nbformat 4.0 mime-types are used for keys, instead of a combination of short names (``text``) and mime-types, and are stored in a ``data`` key, rather than the top-level. i.e. ``output.data['image/png']`` instead of ``output.png``. execute_result ************** Results of executing a cell (as created by ``displayhook`` in Python) are stored in ``execute_result`` outputs. `execute_result` outputs are identical to ``display_data``, adding only a ``execution_count`` field, which must be an integer. .. sourcecode:: python { "output_type" : "execute_result", "execution_count": 42, "data" : { "text/plain" : "[multiline text data]", "image/png": "[base64-encoded-multiline-png-data]", "application/json": { # JSON data is included as-is "json": "data", }, }, "metadata" : { "image/png": { "width": 640, "height": 480, }, }, } .. versionchanged:: nbformat 4.0 ``pyout`` renamed to ``execute_result`` .. versionchanged:: nbformat 4.0 ``prompt_number`` renamed to ``execution_count`` error ***** Failed execution may show an error:: { 'output_type': 'error', 'ename' : str, # Exception name, as a string 'evalue' : str, # Exception value, as a string # The traceback will contain a list of frames, # represented each as a string. 'traceback' : list, } .. versionchanged:: nbformat 4.0 ``pyerr`` renamed to ``error`` .. _raw nbconvert cells: Raw NBConvert cells ------------------- .. _nbconvert: https://nbconvert.readthedocs.org A raw cell is defined as content that should be included *unmodified* in `nbconvert`_ output. For example, this cell could include raw LaTeX for nbconvert to pdf via latex, or restructured text for use in Sphinx documentation. The notebook authoring environment does not render raw cells. The only logic in a raw cell is the `format` metadata field. If defined, it specifies which nbconvert output format is the intended target for the raw cell. When outputting to any other format, the raw cell's contents will be excluded. In the default case when this value is undefined, a raw cell's contents will be included in any nbconvert output, regardless of format. .. sourcecode:: python { "cell_type" : "raw", "metadata" : { # the mime-type of the target nbconvert format. # nbconvert to formats other than this will exclude this cell. "format" : "mime/type" }, "source" : "[some nbformat output text]" } Cell attachments ---------------- Markdown and raw cells can have a number of attachments, typically inline images that can be referenced in the markdown content of a cell. The ``attachments`` dictionary of a cell contains a set of mime-bundles (see :ref:`display_data`) keyed by filename that represents the files attached to the cell. .. note:: The ``attachments`` dictionary is an optional field and can be undefined or empty if the cell does not have any attachments. .. sourcecode:: python { "cell_type" : "markdown", "metadata" : {}, "source" : ["Here is an *inline* image ![inline image](attachment:test.png)"], "attachments" : { "test.png": { "image/png" : "base64-encoded-png-data" } } } Cell ids -------- Since the 4.5 schema release, all cells have an ``id`` field which must be a string of length 1-64 with alphanumeric, `-`, and `_` as legal characters to use. These ids must be unique to any given Notebook following the nbformat spec. The full rules and guidelines for using cells ids is captured in the corresponding `JEP Proposal `_. If attempting to add similiar support to other languages supporting notebooks specs, this `Example PR `_ can be used as a reference to follow. Backward-compatible changes =========================== The notebook format is an evolving format. When backward-compatible changes are made, the notebook format minor version is incremented. When backward-incompatible changes are made, the major version is incremented. As of nbformat 4.x, backward-compatible changes include: - new fields in any dictionary (notebook, cell, output, metadata, etc.) - new cell types - new output types New cell or output types will not be rendered in versions that do not recognize them, but they will be preserved. Because the nbformat python package used to be less strict about validating notebook files, two features have been backported from nbformat 4.x to nbformat 4.0. These are: * ``attachment`` top-level keys in the Markdown and raw cell types (backported from nbformat 4.1) * Mime-bundle attributes are JSON data if the mime-type key ends in ``+json`` (backported from nbformat 4.2) These backports ensure that any valid nbformat 4.4 file is also a valid nbformat 4.0 file. Metadata ======== Metadata is a place that you can put arbitrary JSONable information about your notebook, cell, or output. Because it is a shared namespace, any custom metadata should use a sufficiently unique namespace, such as `metadata.kaylees_md.foo = "bar"`. Metadata fields officially defined for Jupyter notebooks are listed here: Notebook metadata ----------------- The following metadata keys are defined at the notebook level: =========== =============== ============== Key Value Interpretation =========== =============== ============== kernelspec dict A :ref:`kernel specification ` authors list of dicts A list of authors of the document =========== =============== ============== A notebook's authors is a list of dictionaries containing information about each author of the notebook. Currently, only the name is required. Additional fields may be added. .. sourcecode:: python nb.metadata.authors = [ { 'name': 'Fernando Perez', }, { 'name': 'Brian Granger', }, ] Cell metadata ------------- Official Jupyter metadata, as used by Jupyter frontends should be placed in the `metadata.jupyter` namespace, for example `metadata.jupyter.foo = "bar"`. The following metadata keys are defined at the cell level: =========== =============== ============== Key Value Interpretation =========== =============== ============== collapsed bool Whether the cell's output container should be collapsed scrolled bool or 'auto' Whether the cell's output is scrolled, unscrolled, or autoscrolled deletable bool If False, prevent deletion of the cell editable bool If False, prevent editing of the cell (by definition, this also prevents deleting the cell) format 'mime/type' The mime-type of a :ref:`Raw NBConvert Cell ` name str A name for the cell. Should be unique across the notebook. Uniqueness must be verified outside of the json schema. tags list of str A list of string tags on the cell. Commas are not allowed in a tag jupyter dict A namespace holding jupyter specific fields. See docs below for more details execution dict A namespace holding execution specific fields. See docs below for more details =========== =============== ============== The following metadata keys are defined at the cell level within the `jupyter` namespace =============== =============== ============== Key Value Interpretation =============== =============== ============== source_hidden bool Whether the cell's source should be shown outputs_hidden bool Whether the cell's outputs should be shown =============== =============== ============== The following metadata keys are defined at the cell level within the `execution` namespace. These are lower level fields capturing common kernel message timestamps for better visibility in applications where needed. Most users will not look at these directly. ==================== ================ ============== Key Value Interpretation ==================== ================ ============== iopub.execute_input ISO 8601 format Indicates the time at which the kernel broadcasts an execute_input message. This represents the time when request for work was received by the kernel. iopub.status.busy ISO 8601 format Indicates the time at which the iopub channel's kernel status message is 'busy'. This represents the time when work was started by the kernel. shell.execute_reply ISO 8601 format Indicates the time at which the shell channel's execute_reply status message was created. This represents the time when work was completed by the kernel. iopub.status.idle ISO 8601 format Indicates the time at which the iopub channel's kernel status message is 'idle'. This represents the time when the kernel is ready to accept new work. ==================== ================ ============== Output metadata --------------- The following metadata keys are defined for code cell outputs: =========== =============== ============== Key Value Interpretation =========== =============== ============== isolated bool Whether the output should be isolated into an IFrame =========== =============== ============== nbformat-5.9.1/docs/index.rst000066400000000000000000000007001445275403000161300ustar00rootroot00000000000000=========================== The Jupyter Notebook Format =========================== Jupyter (né IPython) notebook files are simple JSON documents, containing text, source code, rich media output, and metadata. Each segment of the document is stored in a cell. Contents: .. toctree:: :maxdepth: 2 format_description markup api changelog Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` nbformat-5.9.1/docs/make.bat000066400000000000000000000161201445275403000156770ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. xml to make Docutils-native XML files echo. pseudoxml to make pseudoxml-XML files for display purposes echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled echo. coverage to run coverage check of the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) REM Check if sphinx-build is available and fallback to Python version if any %SPHINXBUILD% 2> nul if errorlevel 9009 goto sphinx_python goto sphinx_ok :sphinx_python set SPHINXBUILD=python -m sphinx.__init__ %SPHINXBUILD% 2> nul if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) :sphinx_ok if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\nbformat.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\nbformat.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdf" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf cd %~dp0 echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdfja" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf-ja cd %~dp0 echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) if "%1" == "coverage" ( %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage if errorlevel 1 exit /b 1 echo. echo.Testing of coverage in the sources finished, look at the ^ results in %BUILDDIR%/coverage/python.txt. goto end ) if "%1" == "xml" ( %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml if errorlevel 1 exit /b 1 echo. echo.Build finished. The XML files are in %BUILDDIR%/xml. goto end ) if "%1" == "pseudoxml" ( %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml if errorlevel 1 exit /b 1 echo. echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. goto end ) :end nbformat-5.9.1/docs/markup.rst000066400000000000000000000041021445275403000163200ustar00rootroot00000000000000.. _markup: ======================== Supported markup formats ======================== The Jupyter Notebook format supports Markdown in text cells. There is not a strict specification for the flavor of markdown that is supported, but this page should help guide the user / developer in understanding what behavior to expect with Jupyter interfaces and markup languages. What flavor of Markdown does the notebook format support? ========================================================= Most Jupyter Notebook interfaces use the `marked.js `_ JavaScript library for rendering markdown. This supports markdown in the following markdown flavors: * `CommonMark `_. * `GitHub Flavored Markdown `_ See the `Marked.js specification page `_ for more information. .. note:: Currently, as the Marked.js specification changes, so to will the behavior of Markdown in many notebook interfaces. MathJax configuration ===================== There are a few extra modifications that Jupyter interfaces tend to use for rendering markdown. Specifically, they automatically render mathematical equations using `MathJax `_. This is currently the MathJax configuration that is used: .. code:: javascript { tex2jax: { inlineMath: [ ['$','$'], ["\\(","\\)"] ], displayMath: [ ['$$','$$'], ["\\[","\\]"] ], processEscapes: true, processEnvironments: true }, MathML: { extensions: ['content-mathml.js'] }, displayAlign: 'center', "HTML-CSS": { availableFonts: [], imageFont: null, preferredFont: null, webFont: "STIX-Web", styles: {'.MathJax_Display': {"margin": 0}}, linebreaks: { automatic: true } }, } See the `MathJax script for the classic Notebook UI `_ for one example. nbformat-5.9.1/index.js000066400000000000000000000001761445275403000150130ustar00rootroot00000000000000exports.v3 = require("./nbformat/v3/nbformat.v3.schema.json"); exports.v4 = require("./nbformat/v4/nbformat.v4.schema.json"); nbformat-5.9.1/nbformat/000077500000000000000000000000001445275403000151525ustar00rootroot00000000000000nbformat-5.9.1/nbformat/__init__.py000066400000000000000000000140661445275403000172720ustar00rootroot00000000000000"""The Jupyter notebook format Use this module to read or write notebook files as particular nbformat versions. """ # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. from traitlets.log import get_logger from . import v1, v2, v3, v4 from ._version import __version__, version_info from .sentinel import Sentinel __all__ = [ "versions", "validate", "ValidationError", "convert", "from_dict", "NotebookNode", "current_nbformat", "current_nbformat_minor", "NBFormatError", "NO_CONVERT", "reads", "read", "writes", "write", "version_info", "__version__", "Sentinel", ] versions = { 1: v1, 2: v2, 3: v3, 4: v4, } from . import reader # noqa from .converter import convert # noqa from .notebooknode import NotebookNode, from_dict # noqa from .v4 import nbformat as current_nbformat # noqa from .v4 import nbformat_minor as current_nbformat_minor # noqa from .validator import ValidationError, validate # noqa class NBFormatError(ValueError): pass # no-conversion singleton NO_CONVERT = Sentinel( "NO_CONVERT", __name__, """Value to prevent nbformat to convert notebooks to most recent version. """, ) def reads(s, as_version, capture_validation_error=None, **kwargs): """Read a notebook from a string and return the NotebookNode object as the given version. The string can contain a notebook of any version. The notebook will be returned `as_version`, converting, if necessary. Notebook format errors will be logged. Parameters ---------- s : unicode The raw unicode string to read the notebook from. as_version : int The version of the notebook format to return. The notebook will be converted, if necessary. Pass nbformat.NO_CONVERT to prevent conversion. capture_validation_error : dict, optional If provided, a key of "ValidationError" with a value of the ValidationError instance will be added to the dictionary. Returns ------- nb : NotebookNode The notebook that was read. """ nb = reader.reads(s, **kwargs) if as_version is not NO_CONVERT: nb = convert(nb, as_version) try: validate(nb) except ValidationError as e: get_logger().error("Notebook JSON is invalid: %s", e) if isinstance(capture_validation_error, dict): capture_validation_error["ValidationError"] = e return nb def writes(nb, version=NO_CONVERT, capture_validation_error=None, **kwargs): """Write a notebook to a string in a given format in the given nbformat version. Any notebook format errors will be logged. Parameters ---------- nb : NotebookNode The notebook to write. version : int, optional The nbformat version to write. If unspecified, or specified as nbformat.NO_CONVERT, the notebook's own version will be used and no conversion performed. capture_validation_error : dict, optional If provided, a key of "ValidationError" with a value of the ValidationError instance will be added to the dictionary. Returns ------- s : unicode The notebook as a JSON string. """ if version is not NO_CONVERT: nb = convert(nb, version) else: version, _ = reader.get_version(nb) try: validate(nb) except ValidationError as e: get_logger().error("Notebook JSON is invalid: %s", e) if isinstance(capture_validation_error, dict): capture_validation_error["ValidationError"] = e return versions[version].writes_json(nb, **kwargs) def read(fp, as_version, capture_validation_error=None, **kwargs): """Read a notebook from a file as a NotebookNode of the given version. The string can contain a notebook of any version. The notebook will be returned `as_version`, converting, if necessary. Notebook format errors will be logged. Parameters ---------- fp : file or str A file-like object with a read method that returns unicode (use ``io.open()`` in Python 2), or a path to a file. as_version : int The version of the notebook format to return. The notebook will be converted, if necessary. Pass nbformat.NO_CONVERT to prevent conversion. capture_validation_error : dict, optional If provided, a key of "ValidationError" with a value of the ValidationError instance will be added to the dictionary. Returns ------- nb : NotebookNode The notebook that was read. """ try: buf = fp.read() except AttributeError: with open(fp, encoding="utf-8") as f: return reads(f.read(), as_version, capture_validation_error, **kwargs) return reads(buf, as_version, capture_validation_error, **kwargs) def write(nb, fp, version=NO_CONVERT, capture_validation_error=None, **kwargs): """Write a notebook to a file in a given nbformat version. The file-like object must accept unicode input. Parameters ---------- nb : NotebookNode The notebook to write. fp : file or str Any file-like object with a write method that accepts unicode, or a path to write a file. version : int, optional The nbformat version to write. If nb is not this version, it will be converted. If unspecified, or specified as nbformat.NO_CONVERT, the notebook's own version will be used and no conversion performed. capture_validation_error : dict, optional If provided, a key of "ValidationError" with a value of the ValidationError instance will be added to the dictionary. """ s = writes(nb, version, capture_validation_error, **kwargs) if isinstance(s, bytes): s = s.decode("utf8") try: fp.write(s) if not s.endswith("\n"): fp.write("\n") except AttributeError: with open(fp, "w", encoding="utf-8") as f: f.write(s) if not s.endswith("\n"): f.write("\n") nbformat-5.9.1/nbformat/_imports.py000066400000000000000000000020521445275403000173570ustar00rootroot00000000000000""" A simple utility to import something by its string name. Vendored form ipython_genutils """ # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. def import_item(name): """Import and return ``bar`` given the string ``foo.bar``. Calling ``bar = import_item("foo.bar")`` is the functional equivalent of executing the code ``from foo import bar``. Parameters ---------- name : string The fully qualified name of the module/package being imported. Returns ------- mod : module object The module that was imported. """ parts = name.rsplit(".", 1) if len(parts) == 2: # noqa # called with 'foo.bar....' package, obj = parts module = __import__(package, fromlist=[obj]) try: pak = getattr(module, obj) except AttributeError: raise ImportError("No module named %s" % obj) from None return pak else: # called with un-dotted string return __import__(parts[0]) nbformat-5.9.1/nbformat/_struct.py000066400000000000000000000257741445275403000172260ustar00rootroot00000000000000"""A dict subclass that supports attribute style access. Can probably be replaced by types.SimpleNamespace from Python 3.3 """ __all__ = ["Struct"] class Struct(dict): """A dict subclass with attribute style access. This dict subclass has a a few extra features: * Attribute style access. * Protection of class members (like keys, items) when using attribute style access. * The ability to restrict assignment to only existing keys. * Intelligent merging. * Overloaded operators. """ _allownew = True def __init__(self, *args, **kw): """Initialize with a dictionary, another Struct, or data. Parameters ---------- *args : dict, Struct Initialize with one dict or Struct **kw : dict Initialize with key, value pairs. Examples -------- >>> s = Struct(a=10,b=30) >>> s.a 10 >>> s.b 30 >>> s2 = Struct(s,c=30) >>> sorted(s2.keys()) ['a', 'b', 'c'] """ object.__setattr__(self, "_allownew", True) dict.__init__(self, *args, **kw) def __setitem__(self, key, value): """Set an item with check for allownew. Examples -------- >>> s = Struct() >>> s['a'] = 10 >>> s.allow_new_attr(False) >>> s['a'] = 10 >>> s['a'] 10 >>> try: ... s['b'] = 20 ... except KeyError: ... print('this is not allowed') ... this is not allowed """ if not self._allownew and key not in self: raise KeyError("can't create new attribute %s when allow_new_attr(False)" % key) dict.__setitem__(self, key, value) def __setattr__(self, key, value): """Set an attr with protection of class members. This calls :meth:`self.__setitem__` but convert :exc:`KeyError` to :exc:`AttributeError`. Examples -------- >>> s = Struct() >>> s.a = 10 >>> s.a 10 >>> try: ... s.get = 10 ... except AttributeError: ... print("you can't set a class member") ... you can't set a class member """ # If key is an str it might be a class member or instance var if isinstance(key, str): # noqa # I can't simply call hasattr here because it calls getattr, which # calls self.__getattr__, which returns True for keys in # self._data. But I only want keys in the class and in # self.__dict__ if key in self.__dict__ or hasattr(Struct, key): raise AttributeError("attr %s is a protected member of class Struct." % key) try: self.__setitem__(key, value) except KeyError as e: raise AttributeError(e) from None def __getattr__(self, key): """Get an attr by calling :meth:`dict.__getitem__`. Like :meth:`__setattr__`, this method converts :exc:`KeyError` to :exc:`AttributeError`. Examples -------- >>> s = Struct(a=10) >>> s.a 10 >>> type(s.get) <... 'builtin_function_or_method'> >>> try: ... s.b ... except AttributeError: ... print("I don't have that key") ... I don't have that key """ try: result = self[key] except KeyError: raise AttributeError(key) from None else: return result def __iadd__(self, other): """s += s2 is a shorthand for s.merge(s2). Examples -------- >>> s = Struct(a=10,b=30) >>> s2 = Struct(a=20,c=40) >>> s += s2 >>> sorted(s.keys()) ['a', 'b', 'c'] """ self.merge(other) return self def __add__(self, other): """s + s2 -> New Struct made from s.merge(s2). Examples -------- >>> s1 = Struct(a=10,b=30) >>> s2 = Struct(a=20,c=40) >>> s = s1 + s2 >>> sorted(s.keys()) ['a', 'b', 'c'] """ sout = self.copy() sout.merge(other) return sout def __sub__(self, other): """s1 - s2 -> remove keys in s2 from s1. Examples -------- >>> s1 = Struct(a=10,b=30) >>> s2 = Struct(a=40) >>> s = s1 - s2 >>> s {'b': 30} """ sout = self.copy() sout -= other return sout def __isub__(self, other): """Inplace remove keys from self that are in other. Examples -------- >>> s1 = Struct(a=10,b=30) >>> s2 = Struct(a=40) >>> s1 -= s2 >>> s1 {'b': 30} """ for k in other: if k in self: del self[k] return self def __dict_invert(self, data): """Helper function for merge. Takes a dictionary whose values are lists and returns a dict with the elements of each list as keys and the original keys as values. """ outdict = {} for k, lst in data.items(): if isinstance(lst, str): lst = lst.split() # noqa for entry in lst: outdict[entry] = k return outdict def dict(self): # noqa """Get the dict representation of the struct.""" return self def copy(self): """Return a copy as a Struct. Examples -------- >>> s = Struct(a=10,b=30) >>> s2 = s.copy() >>> type(s2) is Struct True """ return Struct(dict.copy(self)) def hasattr(self, key): # noqa """hasattr function available as a method. Implemented like has_key. Examples -------- >>> s = Struct(a=10) >>> s.hasattr('a') True >>> s.hasattr('b') False >>> s.hasattr('get') False """ return key in self def allow_new_attr(self, allow=True): """Set whether new attributes can be created in this Struct. This can be used to catch typos by verifying that the attribute user tries to change already exists in this Struct. """ object.__setattr__(self, "_allownew", allow) def merge(self, __loc_data__=None, __conflict_solve=None, **kw): """Merge two Structs with customizable conflict resolution. This is similar to :meth:`update`, but much more flexible. First, a dict is made from data+key=value pairs. When merging this dict with the Struct S, the optional dictionary 'conflict' is used to decide what to do. If conflict is not given, the default behavior is to preserve any keys with their current value (the opposite of the :meth:`update` method's behavior). Parameters ---------- __loc_data__ : dict, Struct The data to merge into self __conflict_solve : dict The conflict policy dict. The keys are binary functions used to resolve the conflict and the values are lists of strings naming the keys the conflict resolution function applies to. Instead of a list of strings a space separated string can be used, like 'a b c'. **kw : dict Additional key, value pairs to merge in Notes ----- The `__conflict_solve` dict is a dictionary of binary functions which will be used to solve key conflicts. Here is an example:: __conflict_solve = dict( func1=['a','b','c'], func2=['d','e'] ) In this case, the function :func:`func1` will be used to resolve keys 'a', 'b' and 'c' and the function :func:`func2` will be used for keys 'd' and 'e'. This could also be written as:: __conflict_solve = dict(func1='a b c',func2='d e') These functions will be called for each key they apply to with the form:: func1(self['a'], other['a']) The return value is used as the final merged value. As a convenience, merge() provides five (the most commonly needed) pre-defined policies: preserve, update, add, add_flip and add_s. The easiest explanation is their implementation:: preserve = lambda old,new: old update = lambda old,new: new add = lambda old,new: old + new add_flip = lambda old,new: new + old # note change of order! add_s = lambda old,new: old + ' ' + new # only for str! You can use those four words (as strings) as keys instead of defining them as functions, and the merge method will substitute the appropriate functions for you. For more complicated conflict resolution policies, you still need to construct your own functions. Examples -------- This show the default policy: >>> s = Struct(a=10,b=30) >>> s2 = Struct(a=20,c=40) >>> s.merge(s2) >>> sorted(s.items()) [('a', 10), ('b', 30), ('c', 40)] Now, show how to specify a conflict dict: >>> s = Struct(a=10,b=30) >>> s2 = Struct(a=20,b=40) >>> conflict = {'update':'a','add':'b'} >>> s.merge(s2,conflict) >>> sorted(s.items()) [('a', 20), ('b', 70)] """ data_dict = dict(__loc_data__, **kw) # policies for conflict resolution: two argument functions which return # the value that will go in the new struct preserve = lambda old, new: old # noqa update = lambda old, new: new # noqa add = lambda old, new: old + new # noqa add_flip = lambda old, new: new + old # noqa # note change of order! add_s = lambda old, new: old + " " + new # noqa # default policy is to keep current keys when there's a conflict conflict_solve = dict.fromkeys(self, preserve) # the confli_allownewct_solve dictionary is given by the user 'inverted': we # need a name-function mapping, it comes as a function -> names # dict. Make a local copy (b/c we'll make changes), replace user # strings for the three builtin policies and invert it. if __conflict_solve: inv_conflict_solve_user = __conflict_solve.copy() for name, func in [ ("preserve", preserve), ("update", update), ("add", add), ("add_flip", add_flip), ("add_s", add_s), ]: if name in inv_conflict_solve_user: inv_conflict_solve_user[func] = inv_conflict_solve_user[name] del inv_conflict_solve_user[name] conflict_solve.update(self.__dict_invert(inv_conflict_solve_user)) for key in data_dict: if key not in self: self[key] = data_dict[key] else: self[key] = conflict_solve[key](self[key], data_dict[key]) nbformat-5.9.1/nbformat/_version.py000066400000000000000000000015141445275403000173510ustar00rootroot00000000000000"""The version information for nbformat.""" # Use "hatchling version xx.yy.zz" to handle version changes import re try: from importlib.metadata import version except ImportError: from importlib_metadata import version # type:ignore __version__ = version("nbformat") # matches tbump regex in pyproject.toml _version_regex = re.compile( r""" (?P\d+) \. (?P\d+) \. (?P\d+) (?P
((a|b|rc)\d+))?
  (\.
    (?Pdev\d*)
  )?
  """,
    re.VERBOSE,
)

_version_fields = _version_regex.match(__version__).groupdict()  # type:ignore
version_info = tuple(
    field
    for field in (
        int(_version_fields["major"]),
        int(_version_fields["minor"]),
        int(_version_fields["patch"]),
        _version_fields["pre"],
        _version_fields["dev"],
    )
    if field is not None
)
nbformat-5.9.1/nbformat/converter.py000066400000000000000000000050601445275403000175340ustar00rootroot00000000000000"""API for converting notebooks between versions."""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

from . import versions
from .reader import get_version
from .validator import ValidationError


def convert(nb, to_version):
    """Convert a notebook node object to a specific version.  Assumes that
    all the versions starting from 1 to the latest major X are implemented.
    In other words, there should never be a case where v1 v2 v3 v5 exist without
    a v4.  Also assumes that all conversions can be made in one step increments
    between major versions and ignores minor revisions.

    Parameters
    ----------
    nb : NotebookNode
    to_version : int
        Major revision to convert the notebook to.  Can either be an upgrade or
        a downgrade.

    Raises
    ------
    ValueError
        Notebook failed to convert.
    ValueError
        The version specified is invalid or doesn't exist.
    ValidationError
        Conversion failed due to missing expected attributes.
    """

    # Get input notebook version.
    (version, version_minor) = get_version(nb)

    # Check if destination is target version, if so return contents
    if version == to_version:
        return nb

    # If the version exist, try to convert to it one step at a time.
    elif to_version in versions:
        # Get the the version that this recursion will convert to as a step
        # closer to the final revision.  Make sure the newer of the conversion
        # functions is used to perform the conversion.
        if to_version > version:
            step_version = version + 1
            convert_function = versions[step_version].upgrade
        else:
            step_version = version - 1
            convert_function = versions[version].downgrade

        try:
            # Convert and make sure version changed during conversion.
            converted = convert_function(nb)
            if converted.get("nbformat", 1) == version:
                msg = "Failed to convert notebook from v%d to v%d." % (version, step_version)
                raise ValueError(msg)
        except AttributeError as e:
            msg = f"Notebook could not be converted from version {version} to version {step_version} because it's missing a key: {e}"
            raise ValidationError(msg) from None

        # Recursively convert until target version is reached.
        return convert(converted, to_version)
    else:
        raise ValueError(
            "Cannot convert notebook to v%d because that version doesn't exist" % (to_version)
        )
nbformat-5.9.1/nbformat/corpus/000077500000000000000000000000001445275403000164655ustar00rootroot00000000000000nbformat-5.9.1/nbformat/corpus/__init__.py000066400000000000000000000000001445275403000205640ustar00rootroot00000000000000nbformat-5.9.1/nbformat/corpus/tests/000077500000000000000000000000001445275403000176275ustar00rootroot00000000000000nbformat-5.9.1/nbformat/corpus/tests/__init__.py000066400000000000000000000000001445275403000217260ustar00rootroot00000000000000nbformat-5.9.1/nbformat/corpus/tests/test_words.py000066400000000000000000000007221445275403000223770ustar00rootroot00000000000000"""Tests for nbformat corpus"""

# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

from nbformat.corpus import words


def test_generate_corpus_id(recwarn):
    """Test generating a corpus id."""
    assert len(words.generate_corpus_id()) > 7  # noqa
    # 1 in 4294967296 (2^32) times this will fail
    assert words.generate_corpus_id() != words.generate_corpus_id()  # noqa
    assert len(recwarn) == 0  # noqa
nbformat-5.9.1/nbformat/corpus/words.py000066400000000000000000000002041445275403000201710ustar00rootroot00000000000000"""Generate a corpus id."""
import uuid


def generate_corpus_id():
    """Generate a corpus id."""
    return uuid.uuid4().hex[:8]
nbformat-5.9.1/nbformat/current.py000066400000000000000000000140011445275403000172020ustar00rootroot00000000000000"""Deprecated API for working with notebooks

- use nbformat for read/write/validate public API
- use nbformat.vX directly for Python API for composing notebooks
"""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.


import re
import warnings

from traitlets.log import get_logger

from nbformat import v3 as _v_latest
from nbformat.v3 import (
    NotebookNode,
    nbformat,
    nbformat_minor,
    nbformat_schema,
    new_author,
    new_code_cell,
    new_heading_cell,
    new_metadata,
    new_notebook,
    new_output,
    new_text_cell,
    new_worksheet,
    parse_filename,
    to_notebook_json,
)

from . import versions
from .converter import convert
from .reader import reads as reader_reads
from .validator import ValidationError, validate

warnings.warn(
    """nbformat.current is deprecated since before nbformat 3.0

- use nbformat for read/write/validate public API
- use nbformat.vX directly to composing notebooks of a particular version
""",
    DeprecationWarning,
    stacklevel=2,
)

__all__ = [
    "NotebookNode",
    "new_code_cell",
    "new_text_cell",
    "new_notebook",
    "new_output",
    "new_worksheet",
    "parse_filename",
    "new_metadata",
    "new_author",
    "new_heading_cell",
    "nbformat",
    "nbformat_minor",
    "nbformat_schema",
    "to_notebook_json",
    "convert",
    "validate",
    "NBFormatError",
    "parse_py",
    "reads_json",
    "writes_json",
    "reads_py",
    "writes_py",
    "reads",
    "writes",
    "read",
    "write",
]

current_nbformat = nbformat
current_nbformat_minor = nbformat_minor
current_nbformat_module = _v_latest.__name__


class NBFormatError(ValueError):
    """An error raised for an nbformat error."""

    pass


def _warn_format():
    warnings.warn(
        """Non-JSON file support in nbformat is deprecated since nbformat 1.0.
    Use nbconvert to create files of other formats.""",
        stacklevel=2,
    )


def parse_py(s, **kwargs):
    """Parse a string into a (nbformat, string) tuple."""
    nbf = current_nbformat
    nbm = current_nbformat_minor

    pattern = r"# (?P\d+[\.\d+]*)"
    m = re.search(pattern, s)
    if m is not None:
        digits = m.group("nbformat").split(".")
        nbf = int(digits[0])
        if len(digits) > 1:
            nbm = int(digits[1])

    return nbf, nbm, s


def reads_json(nbjson, **kwargs):
    """DEPRECATED, use reads"""
    warnings.warn(
        "reads_json is deprecated since nbformat 3.0, use reads",
        DeprecationWarning,
        stacklevel=2,
    )
    return reads(nbjson)


def writes_json(nb, **kwargs):
    """DEPRECATED, use writes"""
    warnings.warn(
        "writes_json is deprecated since nbformat 3.0, use writes",
        DeprecationWarning,
        stacklevel=2,
    )
    return writes(nb, **kwargs)


def reads_py(s, **kwargs):
    """DEPRECATED: use nbconvert"""
    _warn_format()
    nbf, nbm, s = parse_py(s, **kwargs)
    if nbf in (2, 3):
        nb = versions[nbf].to_notebook_py(s, **kwargs)
    else:
        raise NBFormatError("Unsupported PY nbformat version: %i" % nbf)
    return nb


def writes_py(nb, **kwargs):
    """DEPRECATED: use nbconvert"""
    _warn_format()
    return versions[3].writes_py(nb, **kwargs)


# High level API


def reads(s, format="DEPRECATED", version=current_nbformat, **kwargs):  # noqa
    """Read a notebook from a string and return the NotebookNode object.

    This function properly handles notebooks of any version. The notebook
    returned will always be in the current version's format.

    Parameters
    ----------
    s : unicode
        The raw unicode string to read the notebook from.

    Returns
    -------
    nb : NotebookNode
        The notebook that was read.
    """
    if format not in {"DEPRECATED", "json"}:
        _warn_format()
    nb = reader_reads(s, **kwargs)
    nb = convert(nb, version)
    try:
        with warnings.catch_warnings():
            warnings.filterwarnings("ignore", category=DeprecationWarning)
            validate(nb, repair_duplicate_cell_ids=False)
    except ValidationError as e:
        get_logger().error("Notebook JSON is invalid: %s", e)
    return nb


def writes(nb, format="DEPRECATED", version=current_nbformat, **kwargs):  # noqa
    """Write a notebook to a string in a given format in the current nbformat version.

    This function always writes the notebook in the current nbformat version.

    Parameters
    ----------
    nb : NotebookNode
        The notebook to write.
    version : int
        The nbformat version to write.
        Used for downgrading notebooks.

    Returns
    -------
    s : unicode
        The notebook string.
    """
    if format not in {"DEPRECATED", "json"}:
        _warn_format()
    nb = convert(nb, version)
    try:
        with warnings.catch_warnings():
            warnings.filterwarnings("ignore", category=DeprecationWarning)
            validate(nb, repair_duplicate_cell_ids=False)
    except ValidationError as e:
        get_logger().error("Notebook JSON is invalid: %s", e)
    return versions[version].writes_json(nb, **kwargs)


def read(fp, format="DEPRECATED", **kwargs):  # noqa
    """Read a notebook from a file and return the NotebookNode object.

    This function properly handles notebooks of any version. The notebook
    returned will always be in the current version's format.

    Parameters
    ----------
    fp : file
        Any file-like object with a read method.

    Returns
    -------
    nb : NotebookNode
        The notebook that was read.
    """
    return reads(fp.read(), **kwargs)


def write(nb, fp, format="DEPRECATED", **kwargs):  # noqa
    """Write a notebook to a file in a given format in the current nbformat version.

    This function always writes the notebook in the current nbformat version.

    Parameters
    ----------
    nb : NotebookNode
        The notebook to write.
    fp : file
        Any file-like object with a write method.
    """
    s = writes(nb, **kwargs)
    if isinstance(s, bytes):
        s = s.decode("utf8")
    return fp.write(s)
nbformat-5.9.1/nbformat/json_compat.py000066400000000000000000000077471445275403000200570ustar00rootroot00000000000000"""
Common validator wrapper to provide a uniform usage of other schema validation
libraries.
"""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

import os

import fastjsonschema
import jsonschema
from fastjsonschema import JsonSchemaException as _JsonSchemaException
from jsonschema import Draft4Validator as _JsonSchemaValidator
from jsonschema.exceptions import ErrorTree, ValidationError


class JsonSchemaValidator:
    """A json schema validator."""

    name = "jsonschema"

    def __init__(self, schema):
        """Initialize the validator."""
        self._schema = schema
        self._default_validator = _JsonSchemaValidator(schema)  # Default
        self._validator = self._default_validator

    def validate(self, data):
        """Validate incoming data."""
        self._default_validator.validate(data)

    def iter_errors(self, data, schema=None):
        """Iterate over errors in incoming data."""
        if schema is None:
            return self._default_validator.iter_errors(data)
        if hasattr(self._default_validator, "evolve"):
            return self._default_validator.evolve(schema=schema).iter_errors(data)
        return self._default_validator.iter_errors(data, schema)

    def error_tree(self, errors):
        """Create an error tree for the errors."""
        return ErrorTree(errors=errors)


class FastJsonSchemaValidator(JsonSchemaValidator):
    """A schema validator using fastjsonschema."""

    name = "fastjsonschema"

    def __init__(self, schema):
        """Initialize the validator."""
        super().__init__(schema)
        self._validator = fastjsonschema.compile(schema)

    def validate(self, data):
        """Validate incoming data."""
        try:
            self._validator(data)  # type:ignore[operator]
        except _JsonSchemaException as error:
            raise ValidationError(str(error), schema_path=error.path) from error

    def iter_errors(self, data, schema=None):
        """Iterate over errors in incoming data."""
        if schema is not None:
            return super().iter_errors(data, schema)

        errors = []
        validate_func = self._validator
        try:
            validate_func(data)  # type:ignore[operator]
        except _JsonSchemaException as error:
            errors = [ValidationError(str(error), schema_path=error.path)]

        return errors

    def error_tree(self, errors):
        """Create an error tree for the errors."""
        # fastjsonschema's exceptions don't contain the same information that the jsonschema ValidationErrors
        # do. This method is primarily used for introspecting metadata schema failures so that we can strip
        # them if asked to do so in `nbformat.validate`.
        # Another way forward for compatibility: we could distill both validator errors into a custom collection
        # for this data. Since implementation details of ValidationError is used elsewhere, we would probably
        # just use this data for schema introspection.
        msg = "JSON schema error introspection not enabled for fastjsonschema"
        raise NotImplementedError(msg)


_VALIDATOR_MAP = [
    ("fastjsonschema", fastjsonschema, FastJsonSchemaValidator),
    ("jsonschema", jsonschema, JsonSchemaValidator),
]
VALIDATORS = [item[0] for item in _VALIDATOR_MAP]


def _validator_for_name(validator_name):
    if validator_name not in VALIDATORS:
        msg = f"Invalid validator '{validator_name}' value!\nValid values are: {VALIDATORS}"
        raise ValueError(msg)

    for name, module, validator_cls in _VALIDATOR_MAP:
        if module and validator_name == name:
            return validator_cls
    # we always return something.
    msg = f"Missing validator for {validator_name!r}"
    raise ValueError(msg)


def get_current_validator():
    """
    Return the default validator based on the value of an environment variable.
    """
    validator_name = os.environ.get("NBFORMAT_VALIDATOR", "fastjsonschema")
    return _validator_for_name(validator_name)
nbformat-5.9.1/nbformat/notebooknode.py000066400000000000000000000031321445275403000202110ustar00rootroot00000000000000"""NotebookNode - adding attribute access to dicts"""

from collections.abc import Mapping

from ._struct import Struct


class NotebookNode(Struct):
    """A dict-like node with attribute-access"""

    def __setitem__(self, key, value):
        """Set an item on the notebook."""
        if isinstance(value, Mapping) and not isinstance(value, NotebookNode):
            value = from_dict(value)
        super().__setitem__(key, value)

    def update(self, *args, **kwargs):
        """
        A dict-like update method based on CPython's MutableMapping `update`
        method.
        """
        if len(args) > 1:
            raise TypeError("update expected at most 1 arguments, got %d" % len(args))
        if args:
            other = args[0]
            if isinstance(other, Mapping):  # noqa
                for key in other:
                    self[key] = other[key]
            elif hasattr(other, "keys"):
                for key in other:
                    self[key] = other[key]
            else:
                for key, value in other:
                    self[key] = value
        for key, value in kwargs.items():
            self[key] = value


def from_dict(d):
    """Convert dict to dict-like NotebookNode

    Recursively converts any dict in the container to a NotebookNode.
    This does not check that the contents of the dictionary make a valid
    notebook or part of a notebook.
    """
    if isinstance(d, dict):
        return NotebookNode({k: from_dict(v) for k, v in d.items()})
    elif isinstance(d, (tuple, list)):
        return [from_dict(i) for i in d]
    else:
        return d
nbformat-5.9.1/nbformat/py.typed000066400000000000000000000000001445275403000166370ustar00rootroot00000000000000nbformat-5.9.1/nbformat/reader.py000066400000000000000000000051561445275403000167750ustar00rootroot00000000000000"""API for reading notebooks of different versions"""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

import json

from .validator import ValidationError


class NotJSONError(ValueError):
    """An error raised when an object is not valid JSON."""

    pass


def parse_json(s, **kwargs):
    """Parse a JSON string into a dict."""
    try:
        nb_dict = json.loads(s, **kwargs)
    except ValueError as e:
        message = f"Notebook does not appear to be JSON: {s!r}"
        # Limit the error message to 80 characters.  Display whatever JSON will fit.
        if len(message) > 80:  # noqa
            message = message[:77] + "..."
        raise NotJSONError(message) from e
    return nb_dict


# High level API


def get_version(nb):
    """Get the version of a notebook.

    Parameters
    ----------
    nb : dict
        NotebookNode or dict containing notebook data.

    Returns
    -------
    Tuple containing major (int) and minor (int) version numbers
    """
    major = nb.get("nbformat", 1)
    minor = nb.get("nbformat_minor", 0)
    return (major, minor)


def reads(s, **kwargs):
    """Read a notebook from a json string and return the
    NotebookNode object.

    This function properly reads notebooks of any version.  No version
    conversion is performed.

    Parameters
    ----------
    s : unicode | bytes
        The raw string or bytes object to read the notebook from.

    Returns
    -------
    nb : NotebookNode
        The notebook that was read.

    Raises
    ------
    ValidationError
        Notebook JSON for a given version is missing an expected key and cannot be read.
    NBFormatError
        Specified major version is invalid or unsupported.
    """
    from . import NBFormatError, versions

    nb_dict = parse_json(s, **kwargs)
    (major, minor) = get_version(nb_dict)
    if major in versions:
        try:
            return versions[major].to_notebook_json(nb_dict, minor=minor)
        except AttributeError as e:
            msg = f"The notebook is invalid and is missing an expected key: {e}"
            raise ValidationError(msg) from None
    else:
        raise NBFormatError("Unsupported nbformat version %s" % major)


def read(fp, **kwargs):
    """Read a notebook from a file and return the NotebookNode object.

    This function properly reads notebooks of any version.  No version
    conversion is performed.

    Parameters
    ----------
    fp : file
        Any file-like object with a read method.

    Returns
    -------
    nb : NotebookNode
        The notebook that was read.
    """
    return reads(fp.read(), **kwargs)
nbformat-5.9.1/nbformat/sentinel.py000066400000000000000000000010601445275403000173420ustar00rootroot00000000000000"""Sentinel class for constants with useful reprs"""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.


class Sentinel:
    """Sentinel class for constants with useful reprs"""

    def __init__(self, name, module, docstring=None):
        """Initialize the sentinel."""
        self.name = name
        self.module = module
        if docstring:
            self.__doc__ = docstring

    def __repr__(self):
        """The string repr for the sentinel."""
        return str(self.module) + "." + self.name
nbformat-5.9.1/nbformat/sign.py000066400000000000000000000517431445275403000164760ustar00rootroot00000000000000"""Utilities for signing notebooks"""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

import hashlib
import os
import sys
import typing as t
from collections import OrderedDict
from contextlib import contextmanager
from datetime import datetime, timezone
from hmac import HMAC

try:
    import sqlite3

    # Use adapters recommended by Python 3.12 stdlib docs.
    # https://docs.python.org/3.12/library/sqlite3.html#default-adapters-and-converters-deprecated
    def adapt_datetime_iso(val):
        """Adapt datetime.datetime to timezone-naive ISO 8601 date."""
        return val.isoformat()

    def convert_datetime(val):
        """Convert ISO 8601 datetime to datetime.datetime object."""
        return datetime.fromisoformat(val.decode())

    sqlite3.register_adapter(datetime, adapt_datetime_iso)
    sqlite3.register_converter("datetime", convert_datetime)
except ImportError:
    try:
        from pysqlite2 import dbapi2 as sqlite3  # type:ignore[no-redef]
    except ImportError:
        sqlite3 = None  # type:ignore[assignment]

from base64 import encodebytes

from jupyter_core.application import JupyterApp, base_flags
from traitlets import Any, Bool, Bytes, Callable, Enum, Instance, Integer, Unicode, default, observe
from traitlets.config import LoggingConfigurable, MultipleInstanceError

from . import NO_CONVERT, __version__, read, reads

algorithms_set = hashlib.algorithms_guaranteed
# The shake algorithms in are not compatible with hmac
# due to required length argument in digests
algorithms = [a for a in algorithms_set if not a.startswith("shake_")]


class SignatureStore:
    """Base class for a signature store."""

    def store_signature(self, digest, algorithm):
        """Implement in subclass to store a signature.

        Should not raise if the signature is already stored.
        """
        raise NotImplementedError

    def check_signature(self, digest, algorithm):
        """Implement in subclass to check if a signature is known.

        Return True for a known signature, False for unknown.
        """
        raise NotImplementedError

    def remove_signature(self, digest, algorithm):
        """Implement in subclass to delete a signature.

        Should not raise if the signature is not stored.
        """
        raise NotImplementedError

    def close(self):
        """Close any open connections this store may use.

        If the store maintains any open connections (e.g. to a database),
        they should be closed.
        """
        pass


class MemorySignatureStore(SignatureStore):
    """Non-persistent storage of signatures in memory."""

    cache_size = 65535

    def __init__(self):
        """Initialize a memory signature store."""
        # We really only want an ordered set, but the stdlib has OrderedDict,
        # and it's easy to use a dict as a set.
        self.data = OrderedDict()

    def store_signature(self, digest, algorithm):
        """Store a signature."""
        key = (digest, algorithm)
        # Pop it so it goes to the end when we reinsert it
        self.data.pop(key, None)
        self.data[key] = None

        self._maybe_cull()

    def _maybe_cull(self):
        """If more than cache_size signatures are stored, delete the oldest 25%"""
        if len(self.data) < self.cache_size:
            return

        for _ in range(len(self.data) // 4):
            self.data.popitem(last=False)

    def check_signature(self, digest, algorithm):
        """Check a signature."""
        key = (digest, algorithm)
        if key in self.data:
            # Move it to the end (.move_to_end() method is new in Py3)
            del self.data[key]
            self.data[key] = None
            return True
        return False

    def remove_signature(self, digest, algorithm):
        """Remove a signature."""
        self.data.pop((digest, algorithm), None)


class SQLiteSignatureStore(SignatureStore, LoggingConfigurable):
    """Store signatures in an SQLite database."""

    # 64k entries ~ 12MB
    cache_size = Integer(
        65535,
        help="""The number of notebook signatures to cache.
        When the number of signatures exceeds this value,
        the oldest 25% of signatures will be culled.
        """,
    ).tag(config=True)

    def __init__(self, db_file, **kwargs):
        """Initialize a sql signature store."""
        super().__init__(**kwargs)
        self.db_file = db_file
        self.db = self._connect_db(db_file)

    def close(self):
        """Close the db."""
        if self.db is not None:
            self.db.close()

    def _connect_db(self, db_file):
        kwargs: t.Dict[str, t.Any] = {
            "detect_types": sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES
        }
        db = None
        try:
            db = sqlite3.connect(db_file, **kwargs)
            self.init_db(db)
        except (sqlite3.DatabaseError, sqlite3.OperationalError):
            if db_file != ":memory:":
                old_db_location = db_file + ".bak"
                if db is not None:
                    db.close()
                self.log.warning(
                    (
                        "The signatures database cannot be opened; maybe it is corrupted or encrypted. "
                        "You may need to rerun your notebooks to ensure that they are trusted to run Javascript. "
                        "The old signatures database has been renamed to %s and a new one has been created."
                    ),
                    old_db_location,
                )
                try:
                    os.rename(db_file, old_db_location)
                    db = sqlite3.connect(db_file, **kwargs)
                    self.init_db(db)
                except (sqlite3.DatabaseError, sqlite3.OperationalError, OSError):
                    if db is not None:
                        db.close()
                    self.log.warning(
                        "Failed commiting signatures database to disk. "
                        "You may need to move the database file to a non-networked file system, "
                        "using config option `NotebookNotary.db_file`. "
                        "Using in-memory signatures database for the remainder of this session."
                    )
                    self.db_file = ":memory:"
                    db = sqlite3.connect(":memory:", **kwargs)
                    self.init_db(db)
            else:
                raise
        return db

    def init_db(self, db):
        """Initialize the db."""
        db.execute(
            """
            CREATE TABLE IF NOT EXISTS nbsignatures
            (
                id integer PRIMARY KEY AUTOINCREMENT,
                algorithm text,
                signature text,
                path text,
                last_seen timestamp
            )"""
        )
        db.execute(
            """
            CREATE INDEX IF NOT EXISTS algosig ON nbsignatures(algorithm, signature)
            """
        )
        db.commit()

    def store_signature(self, digest, algorithm):
        """Store a signature in the db."""
        if self.db is None:
            return
        if not self.check_signature(digest, algorithm):
            self.db.execute(
                """
                INSERT INTO nbsignatures (algorithm, signature, last_seen)
                VALUES (?, ?, ?)
                """,
                (algorithm, digest, datetime.now(tz=timezone.utc)),
            )
        else:
            self.db.execute(
                """UPDATE nbsignatures SET last_seen = ? WHERE
                algorithm = ? AND
                signature = ?;
                """,
                (datetime.now(tz=timezone.utc), algorithm, digest),
            )
        self.db.commit()

        # Check size and cull old entries if necessary
        (n,) = self.db.execute("SELECT Count(*) FROM nbsignatures").fetchone()
        if n > self.cache_size:
            self.cull_db()

    def check_signature(self, digest, algorithm):
        """Check a signature against the db."""
        if self.db is None:
            return False
        r = self.db.execute(
            """SELECT id FROM nbsignatures WHERE
            algorithm = ? AND
            signature = ?;
            """,
            (algorithm, digest),
        ).fetchone()
        if r is None:
            return False
        self.db.execute(
            """UPDATE nbsignatures SET last_seen = ? WHERE
            algorithm = ? AND
            signature = ?;
            """,
            (datetime.now(tz=timezone.utc), algorithm, digest),
        )
        self.db.commit()
        return True

    def remove_signature(self, digest, algorithm):
        """Remove a signature from the db."""
        self.db.execute(
            """DELETE FROM nbsignatures WHERE
                algorithm = ? AND
                signature = ?;
            """,
            (algorithm, digest),
        )

        self.db.commit()

    def cull_db(self):
        """Cull oldest 25% of the trusted signatures when the size limit is reached"""
        self.db.execute(
            """DELETE FROM nbsignatures WHERE id IN (
            SELECT id FROM nbsignatures ORDER BY last_seen DESC LIMIT -1 OFFSET ?
        );
        """,
            (max(int(0.75 * self.cache_size), 1),),
        )


def yield_everything(obj):
    """Yield every item in a container as bytes

    Allows any JSONable object to be passed to an HMAC digester
    without having to serialize the whole thing.
    """
    if isinstance(obj, dict):
        for key in sorted(obj):
            value = obj[key]
            assert isinstance(key, str)  # noqa
            yield key.encode()
            yield from yield_everything(value)
    elif isinstance(obj, (list, tuple)):
        for element in obj:
            yield from yield_everything(element)
    elif isinstance(obj, str):
        yield obj.encode("utf8")
    else:
        yield str(obj).encode("utf8")


def yield_code_cells(nb):
    """Iterator that yields all cells in a notebook

    nbformat version independent
    """
    if nb.nbformat >= 4:  # noqa
        for cell in nb["cells"]:
            if cell["cell_type"] == "code":
                yield cell
    elif nb.nbformat == 3:  # noqa
        for ws in nb["worksheets"]:
            for cell in ws["cells"]:
                if cell["cell_type"] == "code":
                    yield cell


@contextmanager
def signature_removed(nb):
    """Context manager for operating on a notebook with its signature removed

    Used for excluding the previous signature when computing a notebook's signature.
    """
    save_signature = nb["metadata"].pop("signature", None)
    try:
        yield
    finally:
        if save_signature is not None:
            nb["metadata"]["signature"] = save_signature


class NotebookNotary(LoggingConfigurable):
    """A class for computing and verifying notebook signatures."""

    data_dir = Unicode(help="""The storage directory for notary secret and database.""").tag(
        config=True
    )

    @default("data_dir")
    def _data_dir_default(self):
        app = None
        try:
            if JupyterApp.initialized():
                app = JupyterApp.instance()
        except MultipleInstanceError:
            pass
        if app is None:
            # create an app, without the global instance
            app = JupyterApp()
            app.initialize(argv=[])
        return app.data_dir

    store_factory = Callable(
        help="""A callable returning the storage backend for notebook signatures.
         The default uses an SQLite database."""
    ).tag(config=True)

    @default("store_factory")
    def _store_factory_default(self):
        def factory():
            if sqlite3 is None:
                self.log.warning("Missing SQLite3, all notebooks will be untrusted!")
                return MemorySignatureStore()
            return SQLiteSignatureStore(self.db_file)

        return factory

    db_file = Unicode(
        help="""The sqlite file in which to store notebook signatures.
        By default, this will be in your Jupyter data directory.
        You can set it to ':memory:' to disable sqlite writing to the filesystem.
        """
    ).tag(config=True)

    @default("db_file")
    def _db_file_default(self):
        if not self.data_dir:
            return ":memory:"
        return os.path.join(self.data_dir, "nbsignatures.db")

    algorithm = Enum(
        algorithms,
        default_value="sha256",
        help="""The hashing algorithm used to sign notebooks.""",
    ).tag(config=True)

    @observe("algorithm")
    def _algorithm_changed(self, change):
        self.digestmod = getattr(hashlib, change["new"])

    digestmod = Any()

    @default("digestmod")
    def _digestmod_default(self):
        return getattr(hashlib, self.algorithm)

    secret_file = Unicode(help="""The file where the secret key is stored.""").tag(config=True)

    @default("secret_file")
    def _secret_file_default(self):
        if not self.data_dir:
            return ""
        return os.path.join(self.data_dir, "notebook_secret")

    secret = Bytes(help="""The secret key with which notebooks are signed.""").tag(config=True)

    @default("secret")
    def _secret_default(self):
        # note : this assumes an Application is running
        if os.path.exists(self.secret_file):
            with open(self.secret_file, "rb") as f:
                return f.read()
        else:
            secret = encodebytes(os.urandom(1024))
            self._write_secret_file(secret)
            return secret

    def __init__(self, **kwargs):
        """Initialize the notary."""
        super().__init__(**kwargs)
        self.store = self.store_factory()

    def _write_secret_file(self, secret):
        """write my secret to my secret_file"""
        self.log.info("Writing notebook-signing key to %s", self.secret_file)
        with open(self.secret_file, "wb") as f:
            f.write(secret)
        try:
            os.chmod(self.secret_file, 0o600)
        except OSError:
            self.log.warning("Could not set permissions on %s", self.secret_file)
        return secret

    def compute_signature(self, nb):
        """Compute a notebook's signature

        by hashing the entire contents of the notebook via HMAC digest.
        """
        hmac = HMAC(self.secret, digestmod=self.digestmod)
        # don't include the previous hash in the content to hash
        with signature_removed(nb):
            # sign the whole thing
            for b in yield_everything(nb):
                hmac.update(b)

        return hmac.hexdigest()

    def check_signature(self, nb):
        """Check a notebook's stored signature

        If a signature is stored in the notebook's metadata,
        a new signature is computed and compared with the stored value.

        Returns True if the signature is found and matches, False otherwise.

        The following conditions must all be met for a notebook to be trusted:
        - a signature is stored in the form 'scheme:hexdigest'
        - the stored scheme matches the requested scheme
        - the requested scheme is available from hashlib
        - the computed hash from notebook_signature matches the stored hash
        """
        if nb.nbformat < 3:  # noqa
            return False
        signature = self.compute_signature(nb)
        return self.store.check_signature(signature, self.algorithm)

    def sign(self, nb):
        """Sign a notebook, indicating that its output is trusted on this machine

        Stores hash algorithm and hmac digest in a local database of trusted notebooks.
        """
        if nb.nbformat < 3:  # noqa
            return
        signature = self.compute_signature(nb)
        self.store.store_signature(signature, self.algorithm)

    def unsign(self, nb):
        """Ensure that a notebook is untrusted

        by removing its signature from the trusted database, if present.
        """
        signature = self.compute_signature(nb)
        self.store.remove_signature(signature, self.algorithm)

    def mark_cells(self, nb, trusted):
        """Mark cells as trusted if the notebook's signature can be verified

        Sets ``cell.metadata.trusted = True | False`` on all code cells,
        depending on the *trusted* parameter. This will typically be the return
        value from ``self.check_signature(nb)``.

        This function is the inverse of check_cells
        """
        if nb.nbformat < 3:  # noqa
            return

        for cell in yield_code_cells(nb):
            cell["metadata"]["trusted"] = trusted

    def _check_cell(self, cell, nbformat_version):
        """Do we trust an individual cell?

        Return True if:

        - cell is explicitly trusted
        - cell has no potentially unsafe rich output

        If a cell has no output, or only simple print statements,
        it will always be trusted.
        """
        # explicitly trusted
        if cell["metadata"].pop("trusted", False):
            return True

        # explicitly safe output
        if nbformat_version >= 4:  # noqa
            unsafe_output_types = ["execute_result", "display_data"]
            safe_keys = {"output_type", "execution_count", "metadata"}
        else:  # v3
            unsafe_output_types = ["pyout", "display_data"]
            safe_keys = {"output_type", "prompt_number", "metadata"}

        for output in cell["outputs"]:
            output_type = output["output_type"]
            if output_type in unsafe_output_types:
                # if there are any data keys not in the safe whitelist
                output_keys = set(output)
                if output_keys.difference(safe_keys):
                    return False

        return True

    def check_cells(self, nb):
        """Return whether all code cells are trusted.

        A cell is trusted if the 'trusted' field in its metadata is truthy, or
        if it has no potentially unsafe outputs.
        If there are no code cells, return True.

        This function is the inverse of mark_cells.
        """
        if nb.nbformat < 3:  # noqa
            return False
        trusted = True
        for cell in yield_code_cells(nb):
            # only distrust a cell if it actually has some output to distrust
            if not self._check_cell(cell, nb.nbformat):
                trusted = False

        return trusted


trust_flags: dict = {
    "reset": (
        {"TrustNotebookApp": {"reset": True}},
        """Delete the trusted notebook cache.
        All previously signed notebooks will become untrusted.
        """,
    ),
}
trust_flags.update(base_flags)


class TrustNotebookApp(JupyterApp):
    """An application for handling notebook trust."""

    version = __version__
    description = """Sign one or more Jupyter notebooks with your key,
    to trust their dynamic (HTML, Javascript) output.

    Otherwise, you will have to re-execute the notebook to see output.
    """
    # This command line tool should use the same config file as the notebook

    @default("config_file_name")
    def _config_file_name_default(self):
        return "jupyter_notebook_config"

    examples = """
    jupyter trust mynotebook.ipynb and_this_one.ipynb
    """

    flags = trust_flags

    reset = Bool(
        False,
        help="""If True, delete the trusted signature cache.
        After reset, all previously signed notebooks will become untrusted.
        """,
    ).tag(config=True)

    notary = Instance(NotebookNotary)

    @default("notary")
    def _notary_default(self):
        return NotebookNotary(parent=self, data_dir=self.data_dir)

    def sign_notebook_file(self, notebook_path):
        """Sign a notebook from the filesystem"""
        if not os.path.exists(notebook_path):
            self.log.error("Notebook missing: %s" % notebook_path)
            self.exit(1)
        with open(notebook_path, encoding="utf8") as f:
            nb = read(f, NO_CONVERT)
        self.sign_notebook(nb, notebook_path)

    def sign_notebook(self, nb, notebook_path=""):
        """Sign a notebook that's been loaded"""
        if self.notary.check_signature(nb):
            print("Notebook already signed: %s" % notebook_path)  # noqa
        else:
            print("Signing notebook: %s" % notebook_path)  # noqa
            self.notary.sign(nb)

    def generate_new_key(self):
        """Generate a new notebook signature key"""
        print("Generating new notebook key: %s" % self.notary.secret_file)  # noqa
        self.notary._write_secret_file(os.urandom(1024))

    def start(self):
        """Start the trust notebook app."""
        if self.reset:
            if os.path.exists(self.notary.db_file):
                print("Removing trusted signature cache: %s" % self.notary.db_file)  # noqa
                os.remove(self.notary.db_file)
            self.generate_new_key()
            return
        if not self.extra_args:
            self.log.debug("Reading notebook from stdin")
            nb_s = sys.stdin.read()
            assert isinstance(nb_s, str)  # noqa
            nb = reads(nb_s, NO_CONVERT)
            self.sign_notebook(nb, "")
        else:
            for notebook_path in self.extra_args:
                self.sign_notebook_file(notebook_path)


main = TrustNotebookApp.launch_instance

if __name__ == "__main__":
    main()
nbformat-5.9.1/nbformat/v1/000077500000000000000000000000001445275403000155005ustar00rootroot00000000000000nbformat-5.9.1/nbformat/v1/__init__.py000066400000000000000000000016001445275403000176060ustar00rootroot00000000000000"""The main module for the v1 notebook format."""

# -----------------------------------------------------------------------------
#  Copyright (C) 2008-2011  The IPython Development Team
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file LICENSE, distributed as part of this software.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------

from .convert import upgrade
from .nbbase import NotebookNode, new_code_cell, new_notebook, new_text_cell
from .nbjson import reads as read_json
from .nbjson import reads as reads_json
from .nbjson import to_notebook as to_notebook_json
from .nbjson import writes as write_json
from .nbjson import writes as writes_json
nbformat-5.9.1/nbformat/v1/convert.py000066400000000000000000000013021445275403000175260ustar00rootroot00000000000000"""Convert notebook to the v1 format."""

# -----------------------------------------------------------------------------
#  Copyright (C) 2008-2011  The IPython Development Team
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file LICENSE, distributed as part of this software.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Code
# -----------------------------------------------------------------------------


def upgrade(nb, orig_version=None):
    """Upgrade a notebook."""
    msg = "Cannot convert to v1 notebook format"
    raise ValueError(msg)
nbformat-5.9.1/nbformat/v1/nbbase.py000066400000000000000000000036011445275403000173040ustar00rootroot00000000000000"""The basic dict based notebook format.

Authors:

* Brian Granger
"""

# -----------------------------------------------------------------------------
#  Copyright (C) 2008-2011  The IPython Development Team
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file LICENSE, distributed as part of this software.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------

from nbformat._struct import Struct

# -----------------------------------------------------------------------------
# Code
# -----------------------------------------------------------------------------


class NotebookNode(Struct):
    """A notebook node object."""

    pass


def from_dict(d):
    """Create notebook node(s) from an object."""
    if isinstance(d, dict):
        newd = NotebookNode()
        for k, v in d.items():
            newd[k] = from_dict(v)
        return newd
    elif isinstance(d, (tuple, list)):
        return [from_dict(i) for i in d]
    else:
        return d


def new_code_cell(code=None, prompt_number=None):
    """Create a new code cell with input and output"""
    cell = NotebookNode()
    cell.cell_type = "code"
    if code is not None:
        cell.code = str(code)
    if prompt_number is not None:
        cell.prompt_number = int(prompt_number)
    return cell


def new_text_cell(text=None):
    """Create a new text cell."""
    cell = NotebookNode()
    if text is not None:
        cell.text = str(text)
    cell.cell_type = "text"
    return cell


def new_notebook(cells=None):
    """Create a notebook by name, id and a list of worksheets."""
    nb = NotebookNode()
    if cells is not None:
        nb.cells = cells
    else:
        nb.cells = []
    return nb
nbformat-5.9.1/nbformat/v1/nbjson.py000066400000000000000000000031641445275403000173470ustar00rootroot00000000000000"""Read and write notebooks in JSON format.

Authors:

* Brian Granger
"""

# -----------------------------------------------------------------------------
#  Copyright (C) 2008-2011  The IPython Development Team
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file LICENSE, distributed as part of this software.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------

import json

from .nbbase import from_dict
from .rwbase import NotebookReader, NotebookWriter

# -----------------------------------------------------------------------------
# Code
# -----------------------------------------------------------------------------


class JSONReader(NotebookReader):
    """A JSON notebook reader."""

    def reads(self, s, **kwargs):
        """Convert a string to a notebook object."""
        nb = json.loads(s, **kwargs)
        return self.to_notebook(nb, **kwargs)

    def to_notebook(self, d, **kwargs):
        """Convert from a raw JSON dict to a nested NotebookNode structure."""
        return from_dict(d)


class JSONWriter(NotebookWriter):
    """A JSON notebook writer."""

    def writes(self, nb, **kwargs):
        """Convert a notebook object to a string."""
        kwargs["indent"] = 4
        return json.dumps(nb, **kwargs)


_reader = JSONReader()
_writer = JSONWriter()

reads = _reader.reads
read = _reader.read
to_notebook = _reader.to_notebook
write = _writer.write
writes = _writer.writes
nbformat-5.9.1/nbformat/v1/rwbase.py000066400000000000000000000027711445275403000173440ustar00rootroot00000000000000"""Base classes and function for readers and writers.

Authors:

* Brian Granger
"""

# -----------------------------------------------------------------------------
#  Copyright (C) 2008-2011  The IPython Development Team
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file LICENSE, distributed as part of this software.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Code
# -----------------------------------------------------------------------------


class NotebookReader:
    """The base notebook reader."""

    def reads(self, s, **kwargs):
        """Read a notebook from a string."""
        msg = "loads must be implemented in a subclass"
        raise NotImplementedError(msg)

    def read(self, fp, **kwargs):
        """Read a notebook from a file like object"""
        return self.reads(fp.read(), **kwargs)


class NotebookWriter:
    """The base notebook writer."""

    def writes(self, nb, **kwargs):
        """Write a notebook to a string."""
        msg = "loads must be implemented in a subclass"
        raise NotImplementedError(msg)

    def write(self, nb, fp, **kwargs):
        """Write a notebook to a file like object"""
        return fp.write(self.writes(nb, **kwargs))
nbformat-5.9.1/nbformat/v2/000077500000000000000000000000001445275403000155015ustar00rootroot00000000000000nbformat-5.9.1/nbformat/v2/__init__.py000066400000000000000000000051741445275403000176210ustar00rootroot00000000000000"""The main API for the v2 notebook format.

Authors:

* Brian Granger
"""

# -----------------------------------------------------------------------------
#  Copyright (C) 2008-2011  The IPython Development Team
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file LICENSE, distributed as part of this software.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------

import os

from .convert import downgrade, upgrade
from .nbbase import (
    NotebookNode,
    new_author,
    new_code_cell,
    new_metadata,
    new_notebook,
    new_output,
    new_text_cell,
    new_worksheet,
)
from .nbjson import reads as read_json
from .nbjson import reads as reads_json
from .nbjson import to_notebook as to_notebook_json
from .nbjson import writes as write_json
from .nbjson import writes as writes_json
from .nbpy import reads as read_py
from .nbpy import reads as reads_py
from .nbpy import to_notebook as to_notebook_py
from .nbpy import writes as write_py
from .nbpy import writes as writes_py

# Implementation removed, vulnerable to DoS attacks
from .nbxml import reads as read_xml
from .nbxml import reads as reads_xml
from .nbxml import to_notebook as to_notebook_xml

# -----------------------------------------------------------------------------
# Code
# -----------------------------------------------------------------------------

nbformat = 2
nbformat_minor = 0


def parse_filename(fname):
    """Parse a notebook filename.

    This function takes a notebook filename and returns the notebook
    format (json/py) and the notebook name. This logic can be
    summarized as follows:

    * notebook.ipynb -> (notebook.ipynb, notebook, json)
    * notebook.json  -> (notebook.json, notebook, json)
    * notebook.py    -> (notebook.py, notebook, py)
    * notebook       -> (notebook.ipynb, notebook, json)

    Parameters
    ----------
    fname : unicode
        The notebook filename. The filename can use a specific filename
        extention (.ipynb, .json, .py) or none, in which case .ipynb will
        be assumed.

    Returns
    -------
    (fname, name, format) : (unicode, unicode, unicode)
        The filename, notebook name and format.
    """
    basename, ext = os.path.splitext(fname)
    if ext in [".ipynb", ".json"]:
        format_ = "json"
    elif ext == ".py":
        format_ = "py"
    else:
        basename = fname
        fname = fname + ".ipynb"
        format_ = "json"
    return fname, basename, format_
nbformat-5.9.1/nbformat/v2/convert.py000066400000000000000000000037651445275403000175460ustar00rootroot00000000000000"""Code for converting notebooks to and from the v2 format.

Authors:

* Brian Granger
* Jonathan Frederic
"""

# -----------------------------------------------------------------------------
#  Copyright (C) 2008-2011  The IPython Development Team
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file LICENSE, distributed as part of this software.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------

from .nbbase import new_code_cell, new_notebook, new_text_cell, new_worksheet

# -----------------------------------------------------------------------------
# Code
# -----------------------------------------------------------------------------


def upgrade(nb, from_version=1):
    """Convert a notebook to the v2 format.

    Parameters
    ----------
    nb : NotebookNode
        The Python representation of the notebook to convert.
    from_version : int
        The version of the notebook to convert from.
    """
    if from_version == 1:
        newnb = new_notebook()
        ws = new_worksheet()
        for cell in nb.cells:
            if cell.cell_type == "code":
                newcell = new_code_cell(
                    input=cell.get("code"), prompt_number=cell.get("prompt_number")
                )
            elif cell.cell_type == "text":
                newcell = new_text_cell("markdown", source=cell.get("text"))
            ws.cells.append(newcell)
        newnb.worksheets.append(ws)
        return newnb
    else:
        raise ValueError("Cannot convert a notebook from v%s to v2" % from_version)


def downgrade(nb):
    """Convert a v2 notebook to v1.

    Parameters
    ----------
    nb : NotebookNode
        The Python representation of the notebook to convert.
    """
    msg = "Downgrade from notebook v2 to v1 is not supported."
    raise Exception(msg)
nbformat-5.9.1/nbformat/v2/nbbase.py000066400000000000000000000126571445275403000173200ustar00rootroot00000000000000"""The basic dict based notebook format.

The Python representation of a notebook is a nested structure of
dictionary subclasses that support attribute access.
The functions in this module are merely
helpers to build the structs in the right form.

Authors:

* Brian Granger
"""

# -----------------------------------------------------------------------------
#  Copyright (C) 2008-2011  The IPython Development Team
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file LICENSE, distributed as part of this software.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------

from nbformat._struct import Struct

# -----------------------------------------------------------------------------
# Code
# -----------------------------------------------------------------------------


class NotebookNode(Struct):
    """A notebook node object."""

    pass


def from_dict(d):
    """Create notebook node(s) from a value."""
    if isinstance(d, dict):
        newd = NotebookNode()
        for k, v in d.items():
            newd[k] = from_dict(v)
        return newd
    elif isinstance(d, (tuple, list)):
        return [from_dict(i) for i in d]
    else:
        return d


def new_output(  # noqa
    output_type=None,
    output_text=None,
    output_png=None,
    output_html=None,
    output_svg=None,
    output_latex=None,
    output_json=None,
    output_javascript=None,
    output_jpeg=None,
    prompt_number=None,
    etype=None,
    evalue=None,
    traceback=None,
):
    """Create a new code cell with input and output"""
    output = NotebookNode()
    if output_type is not None:
        output.output_type = str(output_type)

    if output_type != "pyerr":
        if output_text is not None:
            output.text = str(output_text)
        if output_png is not None:
            output.png = bytes(output_png)
        if output_jpeg is not None:
            output.jpeg = bytes(output_jpeg)
        if output_html is not None:
            output.html = str(output_html)
        if output_svg is not None:
            output.svg = str(output_svg)
        if output_latex is not None:
            output.latex = str(output_latex)
        if output_json is not None:
            output.json = str(output_json)
        if output_javascript is not None:
            output.javascript = str(output_javascript)

    if output_type == "pyout" and prompt_number is not None:
        output.prompt_number = int(prompt_number)

    if output_type == "pyerr":
        if etype is not None:
            output.etype = str(etype)
        if evalue is not None:
            output.evalue = str(evalue)
        if traceback is not None:
            output.traceback = [str(frame) for frame in list(traceback)]

    return output


def new_code_cell(
    input=None, prompt_number=None, outputs=None, language="python", collapsed=False  # noqa
):
    """Create a new code cell with input and output"""
    cell = NotebookNode()
    cell.cell_type = "code"
    if language is not None:
        cell.language = str(language)
    if input is not None:
        cell.input = str(input)
    if prompt_number is not None:
        cell.prompt_number = int(prompt_number)
    if outputs is None:
        cell.outputs = []
    else:
        cell.outputs = outputs
    if collapsed is not None:
        cell.collapsed = bool(collapsed)

    return cell


def new_text_cell(cell_type, source=None, rendered=None):
    """Create a new text cell."""
    cell = NotebookNode()
    if source is not None:
        cell.source = str(source)
    if rendered is not None:
        cell.rendered = str(rendered)
    cell.cell_type = cell_type
    return cell


def new_worksheet(name=None, cells=None):
    """Create a worksheet by name with with a list of cells."""
    ws = NotebookNode()
    if name is not None:
        ws.name = str(name)
    if cells is None:
        ws.cells = []
    else:
        ws.cells = list(cells)
    return ws


def new_notebook(metadata=None, worksheets=None):
    """Create a notebook by name, id and a list of worksheets."""
    nb = NotebookNode()
    nb.nbformat = 2
    if worksheets is None:
        nb.worksheets = []
    else:
        nb.worksheets = list(worksheets)
    if metadata is None:
        nb.metadata = new_metadata()
    else:
        nb.metadata = NotebookNode(metadata)
    return nb


def new_metadata(
    name=None, authors=None, license=None, created=None, modified=None, gistid=None  # noqa
):
    """Create a new metadata node."""
    metadata = NotebookNode()
    if name is not None:
        metadata.name = str(name)
    if authors is not None:
        metadata.authors = list(authors)
    if created is not None:
        metadata.created = str(created)
    if modified is not None:
        metadata.modified = str(modified)
    if license is not None:
        metadata.license = str(license)
    if gistid is not None:
        metadata.gistid = str(gistid)
    return metadata


def new_author(name=None, email=None, affiliation=None, url=None):
    """Create a new author."""
    author = NotebookNode()
    if name is not None:
        author.name = str(name)
    if email is not None:
        author.email = str(email)
    if affiliation is not None:
        author.affiliation = str(affiliation)
    if url is not None:
        author.url = str(url)
    return author
nbformat-5.9.1/nbformat/v2/nbjson.py000066400000000000000000000042161445275403000173470ustar00rootroot00000000000000"""Read and write notebooks in JSON format.

Authors:

* Brian Granger
"""

# -----------------------------------------------------------------------------
#  Copyright (C) 2008-2011  The IPython Development Team
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file LICENSE, distributed as part of this software.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------

import copy
import json

from .nbbase import from_dict
from .rwbase import NotebookReader, NotebookWriter, rejoin_lines, restore_bytes, split_lines

# -----------------------------------------------------------------------------
# Code
# -----------------------------------------------------------------------------


class BytesEncoder(json.JSONEncoder):
    """A JSON encoder that accepts b64 (and other *ascii*) bytestrings."""

    def default(self, obj):
        """The default value of an object."""
        if isinstance(obj, bytes):
            return obj.decode("ascii")
        return json.JSONEncoder.default(self, obj)


class JSONReader(NotebookReader):
    """A JSON notebook reader."""

    def reads(self, s, **kwargs):
        """Convert a string to a notebook."""
        nb = json.loads(s, **kwargs)
        nb = self.to_notebook(nb, **kwargs)
        return nb

    def to_notebook(self, d, **kwargs):
        """Convert a string to a notebook."""
        return restore_bytes(rejoin_lines(from_dict(d)))


class JSONWriter(NotebookWriter):
    """A JSON notebook writer."""

    def writes(self, nb, **kwargs):
        """Convert a notebook object to a string."""
        kwargs["cls"] = BytesEncoder
        kwargs["indent"] = 1
        kwargs["sort_keys"] = True
        if kwargs.pop("split_lines", True):
            nb = split_lines(copy.deepcopy(nb))
        return json.dumps(nb, **kwargs)


_reader = JSONReader()
_writer = JSONWriter()

reads = _reader.reads
read = _reader.read
to_notebook = _reader.to_notebook
write = _writer.write
writes = _writer.writes
nbformat-5.9.1/nbformat/v2/nbpy.py000066400000000000000000000127471445275403000170360ustar00rootroot00000000000000"""Read and write notebooks as regular .py files.

Authors:

* Brian Granger
"""

# -----------------------------------------------------------------------------
#  Copyright (C) 2008-2011  The IPython Development Team
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file LICENSE, distributed as part of this software.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------

import re
from typing import List

from .nbbase import new_code_cell, new_notebook, new_text_cell, new_worksheet
from .rwbase import NotebookReader, NotebookWriter

# -----------------------------------------------------------------------------
# Code
# -----------------------------------------------------------------------------

_encoding_declaration_re = re.compile(r"^#.*coding[:=]\s*([-\w.]+)")


class PyReaderError(Exception):
    """An error raised by the PyReader."""

    pass


class PyReader(NotebookReader):
    """A Python notebook reader."""

    def reads(self, s, **kwargs):
        """Convert a string to a notebook."""
        return self.to_notebook(s, **kwargs)

    def to_notebook(self, s, **kwargs):  # noqa
        """Convert a string to a notebook."""
        lines = s.splitlines()
        cells = []
        cell_lines: List[str] = []
        state = "codecell"
        for line in lines:
            if line.startswith("# ") or _encoding_declaration_re.match(line):
                pass
            elif line.startswith("# "):
                cell = self.new_cell(state, cell_lines)
                if cell is not None:
                    cells.append(cell)
                state = "codecell"
                cell_lines = []
            elif line.startswith("# "):
                cell = self.new_cell(state, cell_lines)
                if cell is not None:
                    cells.append(cell)
                state = "htmlcell"
                cell_lines = []
            elif line.startswith("# "):
                cell = self.new_cell(state, cell_lines)
                if cell is not None:
                    cells.append(cell)
                state = "markdowncell"
                cell_lines = []
            else:
                cell_lines.append(line)
        if cell_lines and state == "codecell":
            cell = self.new_cell(state, cell_lines)
            if cell is not None:
                cells.append(cell)
        ws = new_worksheet(cells=cells)
        nb = new_notebook(worksheets=[ws])
        return nb

    def new_cell(self, state, lines):
        """Create a new cell."""
        if state == "codecell":
            input_ = "\n".join(lines)
            input_ = input_.strip("\n")
            if input_:
                return new_code_cell(input=input_)
        elif state == "htmlcell":
            text = self._remove_comments(lines)
            if text:
                return new_text_cell("html", source=text)
        elif state == "markdowncell":
            text = self._remove_comments(lines)
            if text:
                return new_text_cell("markdown", source=text)

    def _remove_comments(self, lines):
        new_lines = []
        for line in lines:
            if line.startswith("#"):
                new_lines.append(line[2:])
            else:
                new_lines.append(line)
        text = "\n".join(new_lines)
        text = text.strip("\n")
        return text

    def split_lines_into_blocks(self, lines):
        """Split lines into code blocks."""
        if len(lines) == 1:
            yield lines[0]
            raise StopIteration()
        import ast

        source = "\n".join(lines)
        code = ast.parse(source)
        starts = [x.lineno - 1 for x in code.body]
        for i in range(len(starts) - 1):
            yield "\n".join(lines[starts[i] : starts[i + 1]]).strip("\n")
        yield "\n".join(lines[starts[-1] :]).strip("\n")


class PyWriter(NotebookWriter):
    """A Python notebook writer."""

    def writes(self, nb, **kwargs):
        """Convert a notebook object to a string."""
        lines = ["# -*- coding: utf-8 -*-"]
        lines.extend(["# 2", ""])
        for ws in nb.worksheets:
            for cell in ws.cells:
                if cell.cell_type == "code":
                    input_ = cell.get("input")
                    if input_ is not None:
                        lines.extend(["# ", ""])
                        lines.extend(input_.splitlines())
                        lines.append("")
                elif cell.cell_type == "html":
                    input_ = cell.get("source")
                    if input_ is not None:
                        lines.extend(["# ", ""])
                        lines.extend(["# " + line for line in input_.splitlines()])
                        lines.append("")
                elif cell.cell_type == "markdown":
                    input_ = cell.get("source")
                    if input_ is not None:
                        lines.extend(["# ", ""])
                        lines.extend(["# " + line for line in input_.splitlines()])
                        lines.append("")
        lines.append("")
        return str("\n".join(lines))


_reader = PyReader()
_writer = PyWriter()

reads = _reader.reads
read = _reader.read
to_notebook = _reader.to_notebook
write = _writer.write
writes = _writer.writes
nbformat-5.9.1/nbformat/v2/nbxml.py000066400000000000000000000015041445275403000171730ustar00rootroot00000000000000"""REMOVED: Read and write notebook files as XML.
"""


REMOVED_MSG = """\
Reading notebooks as XML has been removed to harden security and avoid
possible denial-of-service attacks.

The XML notebook format was deprecated before the Jupyter (previously IPython)
Notebook was ever released. We are not aware of anyone using it, so we have
removed it.

If you were using this code, and you need to continue using it, feel free to
fork an earlier version of the nbformat package and maintain it yourself.
The issue which prompted this removal is:

https://github.com/jupyter/nbformat/issues/132
"""


def reads(s, **kwargs):
    """REMOVED"""
    raise Exception(REMOVED_MSG)


def read(fp, **kwargs):
    """REMOVED"""
    raise Exception(REMOVED_MSG)


def to_notebook(root, **kwargs):
    """REMOVED"""
    raise Exception(REMOVED_MSG)
nbformat-5.9.1/nbformat/v2/rwbase.py000066400000000000000000000133051445275403000173400ustar00rootroot00000000000000"""Base classes and utilities for readers and writers.

Authors:

* Brian Granger
"""

# -----------------------------------------------------------------------------
#  Copyright (C) 2008-2011  The IPython Development Team
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file LICENSE, distributed as part of this software.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------

from base64 import decodebytes, encodebytes

# -----------------------------------------------------------------------------
# Code
# -----------------------------------------------------------------------------


def restore_bytes(nb):
    """Restore bytes of image data from unicode-only formats.

    Base64 encoding is handled elsewhere.  Bytes objects in the notebook are
    always b64-encoded. We DO NOT encode/decode around file formats.
    """
    for ws in nb.worksheets:
        for cell in ws.cells:
            if cell.cell_type == "code":
                for output in cell.outputs:
                    if "png" in output:
                        output.png = output.png.encode("ascii")
                    if "jpeg" in output:
                        output.jpeg = output.jpeg.encode("ascii")
    return nb


# output keys that are likely to have multiline values
_multiline_outputs = ["text", "html", "svg", "latex", "javascript", "json"]


def rejoin_lines(nb):
    """rejoin multiline text into strings

    For reversing effects of ``split_lines(nb)``.

    This only rejoins lines that have been split, so if text objects were not split
    they will pass through unchanged.

    Used when reading JSON files that may have been passed through split_lines.
    """
    for ws in nb.worksheets:
        for cell in ws.cells:
            if cell.cell_type == "code":
                if "input" in cell and isinstance(cell.input, list):
                    cell.input = "\n".join(cell.input)
                for output in cell.outputs:
                    for key in _multiline_outputs:
                        item = output.get(key, None)
                        if isinstance(item, list):
                            output[key] = "\n".join(item)
            else:  # text cell
                for key in ["source", "rendered"]:
                    item = cell.get(key, None)
                    if isinstance(item, list):
                        cell[key] = "\n".join(item)
    return nb


def split_lines(nb):
    """split likely multiline text into lists of strings

    For file output more friendly to line-based VCS. ``rejoin_lines(nb)`` will
    reverse the effects of ``split_lines(nb)``.

    Used when writing JSON files.
    """
    for ws in nb.worksheets:
        for cell in ws.cells:
            if cell.cell_type == "code":
                if "input" in cell and isinstance(cell.input, str):
                    cell.input = cell.input.splitlines()
                for output in cell.outputs:
                    for key in _multiline_outputs:
                        item = output.get(key, None)
                        if isinstance(item, str):
                            output[key] = item.splitlines()
            else:  # text cell
                for key in ["source", "rendered"]:
                    item = cell.get(key, None)
                    if isinstance(item, str):
                        cell[key] = item.splitlines()
    return nb


# b64 encode/decode are never actually used, because all bytes objects in
# the notebook are already b64-encoded, and we don't need/want to double-encode


def base64_decode(nb):
    """Restore all bytes objects in the notebook from base64-encoded strings.

    Note: This is never used
    """
    for ws in nb.worksheets:
        for cell in ws.cells:
            if cell.cell_type == "code":
                for output in cell.outputs:
                    if "png" in output:
                        if isinstance(output.png, str):
                            output.png = output.png.encode("ascii")
                        output.png = decodebytes(output.png)
                    if "jpeg" in output:
                        if isinstance(output.jpeg, str):
                            output.jpeg = output.jpeg.encode("ascii")
                        output.jpeg = decodebytes(output.jpeg)
    return nb


def base64_encode(nb):
    """Base64 encode all bytes objects in the notebook.

    These will be b64-encoded unicode strings

    Note: This is never used
    """
    for ws in nb.worksheets:
        for cell in ws.cells:
            if cell.cell_type == "code":
                for output in cell.outputs:
                    if "png" in output:
                        output.png = encodebytes(output.png).decode("ascii")
                    if "jpeg" in output:
                        output.jpeg = encodebytes(output.jpeg).decode("ascii")
    return nb


class NotebookReader:
    """A class for reading notebooks."""

    def reads(self, s, **kwargs):
        """Read a notebook from a string."""
        msg = "loads must be implemented in a subclass"
        raise NotImplementedError(msg)

    def read(self, fp, **kwargs):
        """Read a notebook from a file like object"""
        return self.read(fp.read(), **kwargs)


class NotebookWriter:
    """A class for writing notebooks."""

    def writes(self, nb, **kwargs):
        """Write a notebook to a string."""
        msg = "loads must be implemented in a subclass"
        raise NotImplementedError(msg)

    def write(self, nb, fp, **kwargs):
        """Write a notebook to a file like object"""
        return fp.write(self.writes(nb, **kwargs))
nbformat-5.9.1/nbformat/v3/000077500000000000000000000000001445275403000155025ustar00rootroot00000000000000nbformat-5.9.1/nbformat/v3/__init__.py000066400000000000000000000045731445275403000176240ustar00rootroot00000000000000"""The main API for the v3 notebook format.
"""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

__all__ = [
    "NotebookNode",
    "new_code_cell",
    "new_text_cell",
    "new_notebook",
    "new_output",
    "new_worksheet",
    "new_metadata",
    "new_author",
    "new_heading_cell",
    "nbformat",
    "nbformat_minor",
    "nbformat_schema",
    "reads_json",
    "writes_json",
    "read_json",
    "write_json",
    "to_notebook_json",
    "reads_py",
    "writes_py",
    "read_py",
    "write_py",
    "to_notebook_py",
    "downgrade",
    "upgrade",
    "parse_filename",
]

import os

from .convert import downgrade, upgrade
from .nbbase import (
    NotebookNode,
    nbformat,
    nbformat_minor,
    nbformat_schema,
    new_author,
    new_code_cell,
    new_heading_cell,
    new_metadata,
    new_notebook,
    new_output,
    new_text_cell,
    new_worksheet,
)
from .nbjson import reads as read_json
from .nbjson import reads as reads_json
from .nbjson import to_notebook as to_notebook_json
from .nbjson import writes as write_json
from .nbjson import writes as writes_json
from .nbpy import reads as read_py
from .nbpy import reads as reads_py
from .nbpy import to_notebook as to_notebook_py
from .nbpy import writes as write_py
from .nbpy import writes as writes_py


def parse_filename(fname):
    """Parse a notebook filename.

    This function takes a notebook filename and returns the notebook
    format (json/py) and the notebook name. This logic can be
    summarized as follows:

    * notebook.ipynb -> (notebook.ipynb, notebook, json)
    * notebook.json  -> (notebook.json, notebook, json)
    * notebook.py    -> (notebook.py, notebook, py)
    * notebook       -> (notebook.ipynb, notebook, json)

    Parameters
    ----------
    fname : unicode
        The notebook filename. The filename can use a specific filename
        extention (.ipynb, .json, .py) or none, in which case .ipynb will
        be assumed.

    Returns
    -------
    (fname, name, format) : (unicode, unicode, unicode)
        The filename, notebook name and format.
    """
    basename, ext = os.path.splitext(fname)
    if ext in [".ipynb", ".json"]:
        format_ = "json"
    elif ext == ".py":
        format_ = "py"
    else:
        basename = fname
        fname = fname + ".ipynb"
        format_ = "json"
    return fname, basename, format_
nbformat-5.9.1/nbformat/v3/convert.py000066400000000000000000000050521445275403000175360ustar00rootroot00000000000000"""Code for converting notebooks to and from the v2 format."""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

from .nbbase import nbformat, nbformat_minor


def _unbytes(obj):
    """There should be no bytes objects in a notebook

    v2 stores png/jpeg as b64 ascii bytes
    """
    if isinstance(obj, dict):
        for k, v in obj.items():
            obj[k] = _unbytes(v)
    elif isinstance(obj, list):
        for i, v in enumerate(obj):
            obj[i] = _unbytes(v)
    elif isinstance(obj, bytes):
        # only valid bytes are b64-encoded ascii
        obj = obj.decode("ascii")
    return obj


def upgrade(nb, from_version=2, from_minor=0):
    """Convert a notebook to v3.

    Parameters
    ----------
    nb : NotebookNode
        The Python representation of the notebook to convert.
    from_version : int
        The original version of the notebook to convert.
    from_minor : int
        The original minor version of the notebook to convert (only relevant for v >= 3).
    """
    if from_version == 2:  # noqa
        # Mark the original nbformat so consumers know it has been converted.
        nb.nbformat = nbformat
        nb.nbformat_minor = nbformat_minor

        nb.orig_nbformat = 2
        nb = _unbytes(nb)
        for ws in nb["worksheets"]:
            for cell in ws["cells"]:
                cell.setdefault("metadata", {})
        return nb
    elif from_version == 3:  # noqa
        if from_minor != nbformat_minor:
            nb.orig_nbformat_minor = from_minor
        nb.nbformat_minor = nbformat_minor
        return nb
    else:
        msg = (
            "Cannot convert a notebook directly from v%s to v3.  "
            "Try using the nbformat.convert module." % from_version
        )
        raise ValueError(msg)


def heading_to_md(cell):
    """turn heading cell into corresponding markdown"""
    cell.cell_type = "markdown"
    level = cell.pop("level", 1)
    cell.source = "#" * level + " " + cell.source


def raw_to_md(cell):
    """let raw passthrough as markdown"""
    cell.cell_type = "markdown"


def downgrade(nb):
    """Convert a v3 notebook to v2.

    Parameters
    ----------
    nb : NotebookNode
        The Python representation of the notebook to convert.
    """
    if nb.nbformat != 3:  # noqa
        return nb
    nb.nbformat = 2
    for ws in nb.worksheets:
        for cell in ws.cells:
            if cell.cell_type == "heading":
                heading_to_md(cell)
            elif cell.cell_type == "raw":
                raw_to_md(cell)
    return nb
nbformat-5.9.1/nbformat/v3/nbbase.py000066400000000000000000000163231445275403000173130ustar00rootroot00000000000000"""The basic dict based notebook format.

The Python representation of a notebook is a nested structure of
dictionary subclasses that support attribute access.
The functions in this module are merely
helpers to build the structs in the right form.
"""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

import warnings

from nbformat._struct import Struct

# -----------------------------------------------------------------------------
# Code
# -----------------------------------------------------------------------------

# Change this when incrementing the nbformat version
nbformat = 3
nbformat_minor = 0
nbformat_schema = {(3, 0): "nbformat.v3.schema.json"}


class NotebookNode(Struct):
    """A notebook node object."""

    pass


def from_dict(d):
    """Create notebook node(s) from an object."""
    if isinstance(d, dict):
        newd = NotebookNode()
        for k, v in d.items():
            newd[k] = from_dict(v)
        return newd
    elif isinstance(d, (tuple, list)):
        return [from_dict(i) for i in d]
    else:
        return d


def str_passthrough(obj):
    """
    Used to be cast_unicode, add this temporarily to make sure no further breakage.
    """
    if not isinstance(obj, str):
        raise AssertionError
    return obj


def cast_str(obj):
    """Cast an object as a string."""
    if isinstance(obj, bytes):
        # really this should never happend, it should
        # have been base64 encoded before.
        warnings.warn(
            "A notebook got bytes instead of likely base64 encoded values."
            "The content will likely be corrupted.",
            UserWarning,
            stacklevel=3,
        )
        return obj.decode("ascii", "replace")
    else:
        if not isinstance(obj, str):
            raise AssertionError
        return obj


def new_output(  # noqa
    output_type,
    output_text=None,
    output_png=None,
    output_html=None,
    output_svg=None,
    output_latex=None,
    output_json=None,
    output_javascript=None,
    output_jpeg=None,
    prompt_number=None,
    ename=None,
    evalue=None,
    traceback=None,
    stream=None,
    metadata=None,
):
    """Create a new output, to go in the ``cell.outputs`` list of a code cell."""
    output = NotebookNode()
    output.output_type = str(output_type)

    if metadata is None:
        metadata = {}
    if not isinstance(metadata, dict):
        msg = "metadata must be dict"
        raise TypeError(msg)

    if output_type in {"pyout", "display_data"}:
        output.metadata = metadata

    if output_type != "pyerr":
        if output_text is not None:
            output.text = str_passthrough(output_text)
        if output_png is not None:
            output.png = cast_str(output_png)
        if output_jpeg is not None:
            output.jpeg = cast_str(output_jpeg)
        if output_html is not None:
            output.html = str_passthrough(output_html)
        if output_svg is not None:
            output.svg = str_passthrough(output_svg)
        if output_latex is not None:
            output.latex = str_passthrough(output_latex)
        if output_json is not None:
            output.json = str_passthrough(output_json)
        if output_javascript is not None:
            output.javascript = str_passthrough(output_javascript)

    if output_type == "pyout" and prompt_number is not None:
        output.prompt_number = int(prompt_number)

    if output_type == "pyerr":
        if ename is not None:
            output.ename = str_passthrough(ename)
        if evalue is not None:
            output.evalue = str_passthrough(evalue)
        if traceback is not None:
            output.traceback = [str_passthrough(frame) for frame in list(traceback)]

    if output_type == "stream":
        output.stream = "stdout" if stream is None else str_passthrough(stream)

    return output


def new_code_cell(
    input=None,  # noqa
    prompt_number=None,
    outputs=None,
    language="python",
    collapsed=False,
    metadata=None,
):
    """Create a new code cell with input and output"""
    cell = NotebookNode()
    cell.cell_type = "code"
    if language is not None:
        cell.language = str_passthrough(language)
    if input is not None:
        cell.input = str_passthrough(input)
    if prompt_number is not None:
        cell.prompt_number = int(prompt_number)
    if outputs is None:
        cell.outputs = []
    else:
        cell.outputs = outputs
    if collapsed is not None:
        cell.collapsed = bool(collapsed)
    cell.metadata = NotebookNode(metadata or {})

    return cell


def new_text_cell(cell_type, source=None, rendered=None, metadata=None):
    """Create a new text cell."""
    cell = NotebookNode()
    # VERSIONHACK: plaintext -> raw
    # handle never-released plaintext name for raw cells
    if cell_type == "plaintext":
        cell_type = "raw"
    if source is not None:
        cell.source = str_passthrough(source)
    cell.metadata = NotebookNode(metadata or {})
    cell.cell_type = cell_type
    return cell


def new_heading_cell(source=None, level=1, rendered=None, metadata=None):
    """Create a new section cell with a given integer level."""
    cell = NotebookNode()
    cell.cell_type = "heading"
    if source is not None:
        cell.source = str_passthrough(source)
    cell.level = int(level)
    cell.metadata = NotebookNode(metadata or {})
    return cell


def new_worksheet(name=None, cells=None, metadata=None):
    """Create a worksheet by name with with a list of cells."""
    ws = NotebookNode()
    if cells is None:
        ws.cells = []
    else:
        ws.cells = list(cells)
    ws.metadata = NotebookNode(metadata or {})
    return ws


def new_notebook(name=None, metadata=None, worksheets=None):
    """Create a notebook by name, id and a list of worksheets."""
    nb = NotebookNode()
    nb.nbformat = nbformat
    nb.nbformat_minor = nbformat_minor
    if worksheets is None:
        nb.worksheets = []
    else:
        nb.worksheets = list(worksheets)
    if metadata is None:
        nb.metadata = new_metadata()
    else:
        nb.metadata = NotebookNode(metadata)
    if name is not None:
        nb.metadata.name = str_passthrough(name)
    return nb


def new_metadata(
    name=None, authors=None, license=None, created=None, modified=None, gistid=None  # noqa
):
    """Create a new metadata node."""
    metadata = NotebookNode()
    if name is not None:
        metadata.name = str_passthrough(name)
    if authors is not None:
        metadata.authors = list(authors)
    if created is not None:
        metadata.created = str_passthrough(created)
    if modified is not None:
        metadata.modified = str_passthrough(modified)
    if license is not None:
        metadata.license = str_passthrough(license)
    if gistid is not None:
        metadata.gistid = str_passthrough(gistid)
    return metadata


def new_author(name=None, email=None, affiliation=None, url=None):
    """Create a new author."""
    author = NotebookNode()
    if name is not None:
        author.name = str_passthrough(name)
    if email is not None:
        author.email = str_passthrough(email)
    if affiliation is not None:
        author.affiliation = str_passthrough(affiliation)
    if url is not None:
        author.url = str_passthrough(url)
    return author
nbformat-5.9.1/nbformat/v3/nbformat.v3.schema.json000066400000000000000000000276461445275403000220120ustar00rootroot00000000000000{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "description": "IPython Notebook v3.0 JSON schema.",
  "type": "object",
  "additionalProperties": false,
  "required": ["metadata", "nbformat_minor", "nbformat", "worksheets"],
  "properties": {
    "metadata": {
      "description": "Notebook root-level metadata.",
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "kernel_info": {
          "description": "Kernel information.",
          "type": "object",
          "required": ["name", "language"],
          "properties": {
            "name": {
              "description": "Name of the kernel specification.",
              "type": "string"
            },
            "language": {
              "description": "The programming language which this kernel runs.",
              "type": "string"
            },
            "codemirror_mode": {
              "description": "The codemirror mode to use for code in this language.",
              "type": "string"
            }
          }
        },
        "signature": {
          "description": "Hash of the notebook.",
          "type": "string"
        }
      }
    },
    "nbformat_minor": {
      "description": "Notebook format (minor number). Incremented for backward compatible changes to the notebook format.",
      "type": "integer",
      "minimum": 0
    },
    "nbformat": {
      "description": "Notebook format (major number). Incremented between backwards incompatible changes to the notebook format.",
      "type": "integer",
      "minimum": 3,
      "maximum": 3
    },
    "orig_nbformat": {
      "description": "Original notebook format (major number) before converting the notebook between versions.",
      "type": "integer",
      "minimum": 1
    },
    "orig_nbformat_minor": {
      "description": "Original notebook format (minor number) before converting the notebook between versions.",
      "type": "integer",
      "minimum": 0
    },
    "worksheets": {
      "description": "Array of worksheets",
      "type": "array",
      "items": { "$ref": "#/definitions/worksheet" }
    }
  },

  "definitions": {
    "worksheet": {
      "additionalProperties": false,
      "required": ["cells"],
      "properties": {
        "cells": {
          "description": "Array of cells of the current notebook.",
          "type": "array",
          "items": {
            "type": "object",
            "oneOf": [
              { "$ref": "#/definitions/raw_cell" },
              { "$ref": "#/definitions/markdown_cell" },
              { "$ref": "#/definitions/heading_cell" },
              { "$ref": "#/definitions/code_cell" }
            ]
          }
        },
        "metadata": {
          "type": "object",
          "description": "metadata of the current worksheet"
        }
      }
    },
    "raw_cell": {
      "description": "Notebook raw nbconvert cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "source"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["raw"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "format": {
              "description": "Raw cell metadata format for nbconvert.",
              "type": "string"
            },
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          }
        },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "markdown_cell": {
      "description": "Notebook markdown cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "source"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["markdown", "html"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "properties": {
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          },
          "additionalProperties": true
        },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "heading_cell": {
      "description": "Notebook heading cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "source", "level"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["heading"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true
        },
        "source": { "$ref": "#/definitions/misc/source" },
        "level": {
          "description": "Level of heading cells.",
          "type": "integer",
          "minimum": 1
        }
      }
    },

    "code_cell": {
      "description": "Notebook code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "input", "outputs", "language"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["code"]
        },
        "language": {
          "description": "The cell's language (always Python)",
          "type": "string"
        },
        "collapsed": {
          "description": "Whether the cell is collapsed/expanded.",
          "type": "boolean"
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true
        },
        "input": { "$ref": "#/definitions/misc/source" },
        "outputs": {
          "description": "Execution, display, or stream outputs.",
          "type": "array",
          "items": { "$ref": "#/definitions/output" }
        },
        "prompt_number": {
          "description": "The code cell's prompt number. Will be null if the cell has not been run.",
          "type": ["integer", "null"],
          "minimum": 0
        }
      }
    },
    "output": {
      "type": "object",
      "oneOf": [
        { "$ref": "#/definitions/pyout" },
        { "$ref": "#/definitions/display_data" },
        { "$ref": "#/definitions/stream" },
        { "$ref": "#/definitions/pyerr" }
      ]
    },
    "pyout": {
      "description": "Result of executing a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "prompt_number"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["pyout"]
        },
        "prompt_number": {
          "description": "A result's prompt number.",
          "type": ["integer"],
          "minimum": 0
        },
        "text": { "$ref": "#/definitions/misc/multiline_string" },
        "latex": { "$ref": "#/definitions/misc/multiline_string" },
        "png": { "$ref": "#/definitions/misc/multiline_string" },
        "jpeg": { "$ref": "#/definitions/misc/multiline_string" },
        "svg": { "$ref": "#/definitions/misc/multiline_string" },
        "html": { "$ref": "#/definitions/misc/multiline_string" },
        "javascript": { "$ref": "#/definitions/misc/multiline_string" },
        "json": { "$ref": "#/definitions/misc/multiline_string" },
        "pdf": { "$ref": "#/definitions/misc/multiline_string" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      },
      "patternProperties": {
        "^[a-zA-Z0-9]+/[a-zA-Z0-9\\-\\+\\.]+$": {
          "description": "mimetype output (e.g. text/plain), represented as either an array of strings or a string.",
          "$ref": "#/definitions/misc/multiline_string"
        }
      }
    },

    "display_data": {
      "description": "Data displayed as a result of code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["display_data"]
        },
        "text": { "$ref": "#/definitions/misc/multiline_string" },
        "latex": { "$ref": "#/definitions/misc/multiline_string" },
        "png": { "$ref": "#/definitions/misc/multiline_string" },
        "jpeg": { "$ref": "#/definitions/misc/multiline_string" },
        "svg": { "$ref": "#/definitions/misc/multiline_string" },
        "html": { "$ref": "#/definitions/misc/multiline_string" },
        "javascript": { "$ref": "#/definitions/misc/multiline_string" },
        "json": { "$ref": "#/definitions/misc/multiline_string" },
        "pdf": { "$ref": "#/definitions/misc/multiline_string" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      },
      "patternProperties": {
        "[a-zA-Z0-9]+/[a-zA-Z0-9\\-\\+\\.]+$": {
          "description": "mimetype output (e.g. text/plain), represented as either an array of strings or a string.",
          "$ref": "#/definitions/misc/multiline_string"
        }
      }
    },

    "stream": {
      "description": "Stream output from a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "stream", "text"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["stream"]
        },
        "stream": {
          "description": "The stream type/destination.",
          "type": "string"
        },
        "text": {
          "description": "The stream's text output, represented as an array of strings.",
          "$ref": "#/definitions/misc/multiline_string"
        }
      }
    },

    "pyerr": {
      "description": "Output of an error that occurred during code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "ename", "evalue", "traceback"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["pyerr"]
        },
        "ename": {
          "description": "The name of the error.",
          "type": "string"
        },
        "evalue": {
          "description": "The value, or message, of the error.",
          "type": "string"
        },
        "traceback": {
          "description": "The error's traceback, represented as an array of strings.",
          "type": "array",
          "items": { "type": "string" }
        }
      }
    },

    "misc": {
      "metadata_name": {
        "description": "The cell's name. If present, must be a non-empty string.",
        "type": "string",
        "pattern": "^.+$"
      },
      "metadata_tags": {
        "description": "The cell's tags. Tags must be unique, and must not contain commas.",
        "type": "array",
        "uniqueItems": true,
        "items": {
          "type": "string",
          "pattern": "^[^,]+$"
        }
      },
      "source": {
        "description": "Contents of the cell, represented as an array of lines.",
        "$ref": "#/definitions/misc/multiline_string"
      },
      "prompt_number": {
        "description": "The code cell's prompt number. Will be null if the cell has not been run.",
        "type": ["integer", "null"],
        "minimum": 0
      },
      "mimetype": {
        "patternProperties": {
          "^[a-zA-Z0-9\\-\\+]+/[a-zA-Z0-9\\-\\+]+": {
            "description": "The cell's mimetype output (e.g. text/plain), represented as either an array of strings or a string.",
            "$ref": "#/definitions/misc/multiline_string"
          }
        }
      },
      "output_metadata": {
        "description": "Cell output metadata.",
        "type": "object",
        "additionalProperties": true
      },
      "multiline_string": {
        "oneOf": [
          { "type": "string" },
          {
            "type": "array",
            "items": { "type": "string" }
          }
        ]
      }
    }
  }
}
nbformat-5.9.1/nbformat/v3/nbjson.py000066400000000000000000000032161445275403000173470ustar00rootroot00000000000000"""Read and write notebooks in JSON format."""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

import copy
import json

from .nbbase import from_dict
from .rwbase import NotebookReader, NotebookWriter, rejoin_lines, split_lines, strip_transient


class BytesEncoder(json.JSONEncoder):
    """A JSON encoder that accepts b64 (and other *ascii*) bytestrings."""

    def default(self, obj):
        """Get the default value of an object."""
        if isinstance(obj, bytes):
            return obj.decode("ascii")
        return json.JSONEncoder.default(self, obj)


class JSONReader(NotebookReader):
    """A JSON notebook reader."""

    def reads(self, s, **kwargs):
        """Convert a string to a notebook."""
        nb = json.loads(s, **kwargs)
        nb = self.to_notebook(nb, **kwargs)
        nb = strip_transient(nb)
        return nb

    def to_notebook(self, d, **kwargs):
        """Convert a dict to a notebook."""
        return rejoin_lines(from_dict(d))


class JSONWriter(NotebookWriter):
    """A JSON notebook writer."""

    def writes(self, nb, **kwargs):
        """Convert a notebook to a string."""
        kwargs["cls"] = BytesEncoder
        kwargs["indent"] = 1
        kwargs["sort_keys"] = True
        kwargs["separators"] = (",", ": ")
        nb = copy.deepcopy(nb)
        nb = strip_transient(nb)
        if kwargs.pop("split_lines", True):
            nb = split_lines(nb)
        return json.dumps(nb, **kwargs)


_reader = JSONReader()
_writer = JSONWriter()

reads = _reader.reads
read = _reader.read
to_notebook = _reader.to_notebook
write = _writer.write
writes = _writer.writes
nbformat-5.9.1/nbformat/v3/nbpy.py000066400000000000000000000174741445275403000170410ustar00rootroot00000000000000"""Read and write notebooks as regular .py files.

Authors:

* Brian Granger
"""

# -----------------------------------------------------------------------------
#  Copyright (C) 2008-2011  The IPython Development Team
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file LICENSE, distributed as part of this software.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------

import re
from typing import List

from .nbbase import (
    nbformat,
    nbformat_minor,
    new_code_cell,
    new_heading_cell,
    new_notebook,
    new_text_cell,
    new_worksheet,
)
from .rwbase import NotebookReader, NotebookWriter

# -----------------------------------------------------------------------------
# Code
# -----------------------------------------------------------------------------

_encoding_declaration_re = re.compile(r"^#.*coding[:=]\s*([-\w.]+)")


class PyReaderError(Exception):
    """An error raised for a pyreader error."""

    pass


class PyReader(NotebookReader):
    """A python notebook reader."""

    def reads(self, s, **kwargs):
        """Convert a string to a notebook"""
        return self.to_notebook(s, **kwargs)

    def to_notebook(self, s, **kwargs):  # noqa
        """Convert a string to a notebook"""
        lines = s.splitlines()
        cells = []
        cell_lines: List[str] = []
        kwargs = {}
        state = "codecell"
        for line in lines:
            if line.startswith("# ") or _encoding_declaration_re.match(line):
                pass
            elif line.startswith("# "):
                cell = self.new_cell(state, cell_lines, **kwargs)
                if cell is not None:
                    cells.append(cell)
                state = "codecell"
                cell_lines = []
                kwargs = {}
            elif line.startswith("# "):
                cell = self.new_cell(state, cell_lines, **kwargs)
                if cell is not None:
                    cells.append(cell)
                state = "htmlcell"
                cell_lines = []
                kwargs = {}
            elif line.startswith("# "):
                cell = self.new_cell(state, cell_lines, **kwargs)
                if cell is not None:
                    cells.append(cell)
                state = "markdowncell"
                cell_lines = []
                kwargs = {}
            # VERSIONHACK: plaintext -> raw
            elif line.startswith("# ") or line.startswith("# "):
                cell = self.new_cell(state, cell_lines, **kwargs)
                if cell is not None:
                    cells.append(cell)
                state = "rawcell"
                cell_lines = []
                kwargs = {}
            elif line.startswith("# \d)>", line)
                if m is not None:
                    state = "headingcell"
                    kwargs = {}
                    kwargs["level"] = int(m.group("level"))
                else:
                    state = "codecell"
                    kwargs = {}
                    cell_lines = []
            else:
                cell_lines.append(line)
        if cell_lines and state == "codecell":
            cell = self.new_cell(state, cell_lines)
            if cell is not None:
                cells.append(cell)
        ws = new_worksheet(cells=cells)
        nb = new_notebook(worksheets=[ws])
        return nb

    def new_cell(self, state, lines, **kwargs):  # noqa
        """Create a new cell."""
        if state == "codecell":
            input_ = "\n".join(lines)
            input_ = input_.strip("\n")
            if input_:
                return new_code_cell(input=input_)
        elif state == "htmlcell":
            text = self._remove_comments(lines)
            if text:
                return new_text_cell("html", source=text)
        elif state == "markdowncell":
            text = self._remove_comments(lines)
            if text:
                return new_text_cell("markdown", source=text)
        elif state == "rawcell":
            text = self._remove_comments(lines)
            if text:
                return new_text_cell("raw", source=text)
        elif state == "headingcell":
            text = self._remove_comments(lines)
            level = kwargs.get("level", 1)
            if text:
                return new_heading_cell(source=text, level=level)

    def _remove_comments(self, lines):
        new_lines = []
        for line in lines:
            if line.startswith("#"):
                new_lines.append(line[2:])
            else:
                new_lines.append(line)
        text = "\n".join(new_lines)
        text = text.strip("\n")
        return text

    def split_lines_into_blocks(self, lines):
        """Split lines into code blocks."""
        if len(lines) == 1:
            yield lines[0]
            raise StopIteration()
        import ast

        source = "\n".join(lines)
        code = ast.parse(source)
        starts = [x.lineno - 1 for x in code.body]
        for i in range(len(starts) - 1):
            yield "\n".join(lines[starts[i] : starts[i + 1]]).strip("\n")
        yield "\n".join(lines[starts[-1] :]).strip("\n")


class PyWriter(NotebookWriter):
    """A Python notebook writer."""

    def writes(self, nb, **kwargs):  # noqa
        """Convert a notebook to a string."""
        lines = ["# -*- coding: utf-8 -*-"]
        lines.extend(
            [
                "# %i.%i" % (nbformat, nbformat_minor),
                "",
            ]
        )
        for ws in nb.worksheets:
            for cell in ws.cells:
                if cell.cell_type == "code":
                    input_ = cell.get("input")
                    if input_ is not None:
                        lines.extend(["# ", ""])
                        lines.extend(input_.splitlines())
                        lines.append("")
                elif cell.cell_type == "html":
                    input_ = cell.get("source")
                    if input_ is not None:
                        lines.extend(["# ", ""])
                        lines.extend(["# " + line for line in input_.splitlines()])
                        lines.append("")
                elif cell.cell_type == "markdown":
                    input_ = cell.get("source")
                    if input_ is not None:
                        lines.extend(["# ", ""])
                        lines.extend(["# " + line for line in input_.splitlines()])
                        lines.append("")
                elif cell.cell_type == "raw":
                    input_ = cell.get("source")
                    if input_ is not None:
                        lines.extend(["# ", ""])
                        lines.extend(["# " + line for line in input_.splitlines()])
                        lines.append("")
                elif cell.cell_type == "heading":
                    input_ = cell.get("source")
                    level = cell.get("level", 1)
                    if input_ is not None:
                        lines.extend(["# " % level, ""])
                        lines.extend(["# " + line for line in input_.splitlines()])
                        lines.append("")
        lines.append("")
        return "\n".join(lines)


_reader = PyReader()
_writer = PyWriter()

reads = _reader.reads
read = _reader.read
to_notebook = _reader.to_notebook
write = _writer.write
writes = _writer.writes
nbformat-5.9.1/nbformat/v3/rwbase.py000066400000000000000000000142311445275403000173400ustar00rootroot00000000000000"""Base classes and utilities for readers and writers."""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.


from base64 import decodebytes, encodebytes


def restore_bytes(nb):
    """Restore bytes of image data from unicode-only formats.

    Base64 encoding is handled elsewhere.  Bytes objects in the notebook are
    always b64-encoded. We DO NOT encode/decode around file formats.

    Note: this is never used
    """
    for ws in nb.worksheets:
        for cell in ws.cells:
            if cell.cell_type == "code":
                for output in cell.outputs:
                    if "png" in output:
                        output.png = output.png.encode("ascii", "replace")
                    if "jpeg" in output:
                        output.jpeg = output.jpeg.encode("ascii", "replace")
    return nb


# output keys that are likely to have multiline values
_multiline_outputs = ["text", "html", "svg", "latex", "javascript", "json"]


# FIXME: workaround for old splitlines()
def _join_lines(lines):
    """join lines that have been written by splitlines()

    Has logic to protect against `splitlines()`, which
    should have been `splitlines(True)`
    """
    if lines and lines[0].endswith(("\n", "\r")):
        # created by splitlines(True)
        return "".join(lines)
    else:
        # created by splitlines()
        return "\n".join(lines)


def rejoin_lines(nb):
    """rejoin multiline text into strings

    For reversing effects of ``split_lines(nb)``.

    This only rejoins lines that have been split, so if text objects were not split
    they will pass through unchanged.

    Used when reading JSON files that may have been passed through split_lines.
    """
    for ws in nb.worksheets:
        for cell in ws.cells:
            if cell.cell_type == "code":
                if "input" in cell and isinstance(cell.input, list):
                    cell.input = _join_lines(cell.input)
                for output in cell.outputs:
                    for key in _multiline_outputs:
                        item = output.get(key, None)
                        if isinstance(item, list):
                            output[key] = _join_lines(item)
            else:  # text, heading cell
                for key in ["source", "rendered"]:
                    item = cell.get(key, None)
                    if isinstance(item, list):
                        cell[key] = _join_lines(item)
    return nb


def split_lines(nb):
    """split likely multiline text into lists of strings

    For file output more friendly to line-based VCS. ``rejoin_lines(nb)`` will
    reverse the effects of ``split_lines(nb)``.

    Used when writing JSON files.
    """
    for ws in nb.worksheets:
        for cell in ws.cells:
            if cell.cell_type == "code":
                if "input" in cell and isinstance(cell.input, str):
                    cell.input = cell.input.splitlines(True)
                for output in cell.outputs:
                    for key in _multiline_outputs:
                        item = output.get(key, None)
                        if isinstance(item, str):
                            output[key] = item.splitlines(True)
            else:  # text, heading cell
                for key in ["source", "rendered"]:
                    item = cell.get(key, None)
                    if isinstance(item, str):
                        cell[key] = item.splitlines(True)
    return nb


# b64 encode/decode are never actually used, because all bytes objects in
# the notebook are already b64-encoded, and we don't need/want to double-encode


def base64_decode(nb):
    """Restore all bytes objects in the notebook from base64-encoded strings.

    Note: This is never used
    """
    for ws in nb.worksheets:
        for cell in ws.cells:
            if cell.cell_type == "code":
                for output in cell.outputs:
                    if "png" in output:
                        if isinstance(output.png, str):
                            output.png = output.png.encode("ascii")
                        output.png = decodebytes(output.png)
                    if "jpeg" in output:
                        if isinstance(output.jpeg, str):
                            output.jpeg = output.jpeg.encode("ascii")
                        output.jpeg = decodebytes(output.jpeg)
    return nb


def base64_encode(nb):
    """Base64 encode all bytes objects in the notebook.

    These will be b64-encoded unicode strings

    Note: This is never used
    """
    for ws in nb.worksheets:
        for cell in ws.cells:
            if cell.cell_type == "code":
                for output in cell.outputs:
                    if "png" in output:
                        output.png = encodebytes(output.png).decode("ascii")
                    if "jpeg" in output:
                        output.jpeg = encodebytes(output.jpeg).decode("ascii")
    return nb


def strip_transient(nb):
    """Strip transient values that shouldn't be stored in files.

    This should be called in *both* read and write.
    """
    nb.pop("orig_nbformat", None)
    nb.pop("orig_nbformat_minor", None)
    for ws in nb["worksheets"]:
        for cell in ws["cells"]:
            cell.get("metadata", {}).pop("trusted", None)
            # strip cell.trusted even though it shouldn't be used,
            # since it's where the transient value used to be stored.
            cell.pop("trusted", None)
    return nb


class NotebookReader:
    """A class for reading notebooks."""

    def reads(self, s, **kwargs):
        """Read a notebook from a string."""
        msg = "loads must be implemented in a subclass"
        raise NotImplementedError(msg)

    def read(self, fp, **kwargs):
        """Read a notebook from a file like object"""
        nbs = fp.read()
        return self.reads(nbs, **kwargs)


class NotebookWriter:
    """A class for writing notebooks."""

    def writes(self, nb, **kwargs):
        """Write a notebook to a string."""
        msg = "loads must be implemented in a subclass"
        raise NotImplementedError(msg)

    def write(self, nb, fp, **kwargs):
        """Write a notebook to a file like object"""
        nbs = self.writes(nb, **kwargs)
        return fp.write(nbs)
nbformat-5.9.1/nbformat/v4/000077500000000000000000000000001445275403000155035ustar00rootroot00000000000000nbformat-5.9.1/nbformat/v4/__init__.py000066400000000000000000000014201445275403000176110ustar00rootroot00000000000000"""The main API for the v4 notebook format."""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

__all__ = [
    "nbformat",
    "nbformat_minor",
    "nbformat_schema",
    "new_code_cell",
    "new_markdown_cell",
    "new_raw_cell",
    "new_notebook",
    "new_output",
    "output_from_msg",
    "reads",
    "writes",
    "to_notebook",
    "downgrade",
    "upgrade",
]

from .convert import downgrade, upgrade
from .nbbase import (
    nbformat,
    nbformat_minor,
    nbformat_schema,
    new_code_cell,
    new_markdown_cell,
    new_notebook,
    new_output,
    new_raw_cell,
    output_from_msg,
)
from .nbjson import reads, to_notebook, writes

reads_json = reads
writes_json = writes
to_notebook_json = to_notebook
nbformat-5.9.1/nbformat/v4/convert.py000066400000000000000000000223631445275403000175430ustar00rootroot00000000000000"""Code for converting notebooks to and from v3."""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

import json
import re

from traitlets.log import get_logger

from nbformat import v3, validator

from .nbbase import NotebookNode, nbformat, nbformat_minor, random_cell_id


def _warn_if_invalid(nb, version):
    """Log validation errors, if there are any."""
    from nbformat import ValidationError, validate

    try:
        validate(nb, version=version)
    except ValidationError as e:
        get_logger().error("Notebook JSON is not valid v%i: %s", version, e)


def upgrade(nb, from_version=None, from_minor=None):  # noqa
    """Convert a notebook to latest v4.

    Parameters
    ----------
    nb : NotebookNode
        The Python representation of the notebook to convert.
    from_version : int
        The original version of the notebook to convert.
    from_minor : int
        The original minor version of the notebook to convert (only relevant for v >= 3).
    """
    if not from_version:
        from_version = nb["nbformat"]
    if not from_minor:
        if "nbformat_minor" not in nb:
            if from_version == 4:  # noqa
                msg = "The v4 notebook does not include the nbformat minor, which is needed."
                raise validator.ValidationError(msg)
            else:
                from_minor = 0
        else:
            from_minor = nb["nbformat_minor"]

    if from_version == 3:  # noqa
        # Validate the notebook before conversion
        _warn_if_invalid(nb, from_version)

        # Mark the original nbformat so consumers know it has been converted
        orig_nbformat = nb.pop("orig_nbformat", None)
        orig_nbformat_minor = nb.pop("orig_nbformat_minor", None)
        nb.metadata.orig_nbformat = orig_nbformat or 3
        nb.metadata.orig_nbformat_minor = orig_nbformat_minor or 0

        # Mark the new format
        nb.nbformat = nbformat
        nb.nbformat_minor = nbformat_minor

        # remove worksheet(s)
        nb["cells"] = cells = []
        # In the unlikely event of multiple worksheets,
        # they will be flattened
        for ws in nb.pop("worksheets", []):
            # upgrade each cell
            for cell in ws["cells"]:
                cells.append(upgrade_cell(cell))
        # upgrade metadata
        nb.metadata.pop("name", "")
        nb.metadata.pop("signature", "")
        # Validate the converted notebook before returning it
        _warn_if_invalid(nb, nbformat)
        return nb
    elif from_version == 4:  # noqa
        if from_minor == nbformat_minor:
            return nb

        # other versions migration code e.g.
        # if from_minor < 3:
        # if from_minor < 4:

        if from_minor < 5:  # noqa
            for cell in nb.cells:
                cell.id = random_cell_id()

        nb.metadata.orig_nbformat_minor = from_minor
        nb.nbformat_minor = nbformat_minor

        return nb
    else:
        raise ValueError(
            "Cannot convert a notebook directly from v%s to v4.  "
            "Try using the nbformat.convert module." % from_version
        )


def upgrade_cell(cell):
    """upgrade a cell from v3 to v4

    heading cell:
        - -> markdown heading
    code cell:
        - remove language metadata
        - cell.input -> cell.source
        - cell.prompt_number -> cell.execution_count
        - update outputs
    """
    cell.setdefault("metadata", NotebookNode())
    cell.id = random_cell_id()
    if cell.cell_type == "code":
        cell.pop("language", "")
        if "collapsed" in cell:
            cell.metadata["collapsed"] = cell.pop("collapsed")
        cell.source = cell.pop("input", "")
        cell.execution_count = cell.pop("prompt_number", None)
        cell.outputs = upgrade_outputs(cell.outputs)
    elif cell.cell_type == "heading":
        cell.cell_type = "markdown"
        level = cell.pop("level", 1)
        cell.source = "{hashes} {single_line}".format(
            hashes="#" * level,
            single_line=" ".join(cell.get("source", "").splitlines()),
        )
    elif cell.cell_type == "html":
        # Technically, this exists. It will never happen in practice.
        cell.cell_type = "markdown"
    return cell


def downgrade_cell(cell):
    """downgrade a cell from v4 to v3

    code cell:
        - set cell.language
        - cell.input <- cell.source
        - cell.prompt_number <- cell.execution_count
        - update outputs
    markdown cell:
        - single-line heading -> heading cell
    """
    if cell.cell_type == "code":
        cell.language = "python"
        cell.input = cell.pop("source", "")
        cell.prompt_number = cell.pop("execution_count", None)
        cell.collapsed = cell.metadata.pop("collapsed", False)
        cell.outputs = downgrade_outputs(cell.outputs)
    elif cell.cell_type == "markdown":
        source = cell.get("source", "")
        if "\n" not in source and source.startswith("#"):
            match = re.match(r"(#+)\s*(.*)", source)
            assert match is not None  # noqa
            prefix, text = match.groups()
            cell.cell_type = "heading"
            cell.source = text
            cell.level = len(prefix)
    cell.pop("id", None)
    cell.pop("attachments", None)
    return cell


_mime_map = {
    "text": "text/plain",
    "html": "text/html",
    "svg": "image/svg+xml",
    "png": "image/png",
    "jpeg": "image/jpeg",
    "latex": "text/latex",
    "json": "application/json",
    "javascript": "application/javascript",
}


def to_mime_key(d):
    """convert dict with v3 aliases to plain mime-type keys"""
    for alias, mime in _mime_map.items():
        if alias in d:
            d[mime] = d.pop(alias)
    return d


def from_mime_key(d):
    """convert dict with mime-type keys to v3 aliases"""
    d2 = {}
    for alias, mime in _mime_map.items():
        if mime in d:
            d2[alias] = d[mime]
    return d2


def upgrade_output(output):
    """upgrade a single code cell output from v3 to v4

    - pyout -> execute_result
    - pyerr -> error
    - output.type -> output.data.mime/type
    - mime-type keys
    - stream.stream -> stream.name
    """
    if output["output_type"] in {"pyout", "display_data"}:
        output.setdefault("metadata", NotebookNode())
        if output["output_type"] == "pyout":
            output["output_type"] = "execute_result"
            output["execution_count"] = output.pop("prompt_number", None)

        # move output data into data sub-dict
        data = {}
        for key in list(output):
            if key in {"output_type", "execution_count", "metadata"}:
                continue
            data[key] = output.pop(key)
        to_mime_key(data)
        output["data"] = data
        to_mime_key(output.metadata)
        if "application/json" in data:
            data["application/json"] = json.loads(data["application/json"])
        # promote ascii bytes (from v2) to unicode
        for key in ("image/png", "image/jpeg"):
            if key in data and isinstance(data[key], bytes):
                data[key] = data[key].decode("ascii")
    elif output["output_type"] == "pyerr":
        output["output_type"] = "error"
    elif output["output_type"] == "stream":
        output["name"] = output.pop("stream", "stdout")
    return output


def downgrade_output(output):
    """downgrade a single code cell output to v3 from v4

    - pyout <- execute_result
    - pyerr <- error
    - output.data.mime/type -> output.type
    - un-mime-type keys
    - stream.stream <- stream.name
    """
    if output["output_type"] in {"execute_result", "display_data"}:
        if output["output_type"] == "execute_result":
            output["output_type"] = "pyout"
            output["prompt_number"] = output.pop("execution_count", None)

        # promote data dict to top-level output namespace
        data = output.pop("data", {})
        if "application/json" in data:
            data["application/json"] = json.dumps(data["application/json"])
        data = from_mime_key(data)
        output.update(data)
        from_mime_key(output.get("metadata", {}))
    elif output["output_type"] == "error":
        output["output_type"] = "pyerr"
    elif output["output_type"] == "stream":
        output["stream"] = output.pop("name")
    return output


def upgrade_outputs(outputs):
    """upgrade outputs of a code cell from v3 to v4"""
    return [upgrade_output(op) for op in outputs]


def downgrade_outputs(outputs):
    """downgrade outputs of a code cell to v3 from v4"""
    return [downgrade_output(op) for op in outputs]


def downgrade(nb):
    """Convert a v4 notebook to v3.

    Parameters
    ----------
    nb : NotebookNode
        The Python representation of the notebook to convert.
    """
    if nb.nbformat != nbformat:
        return nb

    # Validate the notebook before conversion
    _warn_if_invalid(nb, nbformat)

    nb.nbformat = v3.nbformat
    nb.nbformat_minor = v3.nbformat_minor
    cells = [downgrade_cell(cell) for cell in nb.pop("cells")]
    nb.worksheets = [v3.new_worksheet(cells=cells)]
    nb.metadata.setdefault("name", "")

    # Validate the converted notebook before returning it
    _warn_if_invalid(nb, v3.nbformat)

    nb.orig_nbformat = nb.metadata.pop("orig_nbformat", nbformat)
    nb.orig_nbformat_minor = nb.metadata.pop("orig_nbformat_minor", nbformat_minor)

    return nb
nbformat-5.9.1/nbformat/v4/nbbase.py000066400000000000000000000106701445275403000173130ustar00rootroot00000000000000"""Python API for composing notebook elements

The Python representation of a notebook is a nested structure of
dictionary subclasses that support attribute access.
The functions in this module are merely helpers to build the structs
in the right form.
"""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

from nbformat.corpus.words import generate_corpus_id as random_cell_id
from nbformat.notebooknode import NotebookNode

# Change the nbformat_minor and nbformat_schema variables when incrementing the
# nbformat version

# current major version
nbformat = 4

# current minor version
nbformat_minor = 5

# schema files for (major, minor) version tuples. (None, None) means the current version
nbformat_schema = {
    (None, None): "nbformat.v4.schema.json",
    (4, 0): "nbformat.v4.0.schema.json",
    (4, 1): "nbformat.v4.1.schema.json",
    (4, 2): "nbformat.v4.2.schema.json",
    (4, 3): "nbformat.v4.3.schema.json",
    (4, 4): "nbformat.v4.4.schema.json",
    (4, 5): "nbformat.v4.5.schema.json",
}


def validate(node, ref=None):
    """validate a v4 node"""
    from nbformat import validate as validate_orig

    return validate_orig(node, ref=ref, version=nbformat)


def new_output(output_type, data=None, **kwargs):
    """Create a new output, to go in the ``cell.outputs`` list of a code cell."""
    output = NotebookNode(output_type=output_type)

    # populate defaults:
    if output_type == "stream":
        output.name = "stdout"
        output.text = ""
    elif output_type == "display_data":
        output.metadata = NotebookNode()
        output.data = NotebookNode()
    elif output_type == "execute_result":
        output.metadata = NotebookNode()
        output.data = NotebookNode()
        output.execution_count = None
    elif output_type == "error":
        output.ename = "NotImplementedError"
        output.evalue = ""
        output.traceback = []

    # load from args:
    output.update(kwargs)
    if data is not None:
        output.data = data
    # validate
    validate(output, output_type)
    return output


def output_from_msg(msg):
    """Create a NotebookNode for an output from a kernel's IOPub message.

    Returns
    -------
    NotebookNode: the output as a notebook node.

    Raises
    ------
    ValueError: if the message is not an output message.

    """
    msg_type = msg["header"]["msg_type"]
    content = msg["content"]

    if msg_type == "execute_result":
        return new_output(
            output_type=msg_type,
            metadata=content["metadata"],
            data=content["data"],
            execution_count=content["execution_count"],
        )
    elif msg_type == "stream":
        return new_output(
            output_type=msg_type,
            name=content["name"],
            text=content["text"],
        )
    elif msg_type == "display_data":
        return new_output(
            output_type=msg_type,
            metadata=content["metadata"],
            data=content["data"],
        )
    elif msg_type == "error":
        return new_output(
            output_type=msg_type,
            ename=content["ename"],
            evalue=content["evalue"],
            traceback=content["traceback"],
        )
    else:
        raise ValueError("Unrecognized output msg type: %r" % msg_type)


def new_code_cell(source="", **kwargs):
    """Create a new code cell"""
    cell = NotebookNode(
        id=random_cell_id(),
        cell_type="code",
        metadata=NotebookNode(),
        execution_count=None,
        source=source,
        outputs=[],
    )
    cell.update(kwargs)

    validate(cell, "code_cell")
    return cell


def new_markdown_cell(source="", **kwargs):
    """Create a new markdown cell"""
    cell = NotebookNode(
        id=random_cell_id(),
        cell_type="markdown",
        source=source,
        metadata=NotebookNode(),
    )
    cell.update(kwargs)

    validate(cell, "markdown_cell")
    return cell


def new_raw_cell(source="", **kwargs):
    """Create a new raw cell"""
    cell = NotebookNode(
        id=random_cell_id(),
        cell_type="raw",
        source=source,
        metadata=NotebookNode(),
    )
    cell.update(kwargs)

    validate(cell, "raw_cell")
    return cell


def new_notebook(**kwargs):
    """Create a new notebook"""
    nb = NotebookNode(
        nbformat=nbformat,
        nbformat_minor=nbformat_minor,
        metadata=NotebookNode(),
        cells=[],
    )
    nb.update(kwargs)
    validate(nb)
    return nb
nbformat-5.9.1/nbformat/v4/nbformat.v4.0.schema.json000066400000000000000000000300341445275403000221330ustar00rootroot00000000000000{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "description": "IPython Notebook v4.0 JSON schema.",
  "type": "object",
  "additionalProperties": false,
  "required": ["metadata", "nbformat_minor", "nbformat", "cells"],
  "properties": {
    "metadata": {
      "description": "Notebook root-level metadata.",
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "kernelspec": {
          "description": "Kernel information.",
          "type": "object",
          "required": ["name", "display_name"],
          "properties": {
            "name": {
              "description": "Name of the kernel specification.",
              "type": "string"
            },
            "display_name": {
              "description": "Name to display in UI.",
              "type": "string"
            }
          }
        },
        "language_info": {
          "description": "Kernel information.",
          "type": "object",
          "required": ["name"],
          "properties": {
            "name": {
              "description": "The programming language which this kernel runs.",
              "type": "string"
            },
            "codemirror_mode": {
              "description": "The codemirror mode to use for code in this language.",
              "oneOf": [{ "type": "string" }, { "type": "object" }]
            },
            "file_extension": {
              "description": "The file extension for files in this language.",
              "type": "string"
            },
            "mimetype": {
              "description": "The mimetype corresponding to files in this language.",
              "type": "string"
            },
            "pygments_lexer": {
              "description": "The pygments lexer to use for code in this language.",
              "type": "string"
            }
          }
        },
        "orig_nbformat": {
          "description": "Original notebook format (major number) before converting the notebook between versions. This should never be written to a file.",
          "type": "integer",
          "minimum": 1
        }
      }
    },
    "nbformat_minor": {
      "description": "Notebook format (minor number). Incremented for backward compatible changes to the notebook format.",
      "type": "integer",
      "minimum": 0
    },
    "nbformat": {
      "description": "Notebook format (major number). Incremented between backwards incompatible changes to the notebook format.",
      "type": "integer",
      "minimum": 4,
      "maximum": 4
    },
    "cells": {
      "description": "Array of cells of the current notebook.",
      "type": "array",
      "items": { "$ref": "#/definitions/cell" }
    }
  },

  "definitions": {
    "cell": {
      "type": "object",
      "oneOf": [
        { "$ref": "#/definitions/raw_cell" },
        { "$ref": "#/definitions/markdown_cell" },
        { "$ref": "#/definitions/code_cell" }
      ]
    },

    "raw_cell": {
      "description": "Notebook raw nbconvert cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "metadata", "source"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["raw"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "format": {
              "description": "Raw cell metadata format for nbconvert.",
              "type": "string"
            },
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          }
        },
        "attachments": { "$ref": "#/definitions/misc/attachments" },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "markdown_cell": {
      "description": "Notebook markdown cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "metadata", "source"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["markdown"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "properties": {
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          },
          "additionalProperties": true
        },
        "attachments": { "$ref": "#/definitions/misc/attachments" },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "code_cell": {
      "description": "Notebook code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "cell_type",
        "metadata",
        "source",
        "outputs",
        "execution_count"
      ],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["code"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "collapsed": {
              "description": "Whether the cell is collapsed/expanded.",
              "type": "boolean"
            },
            "scrolled": {
              "description": "Whether the cell's output is scrolled, unscrolled, or autoscrolled.",
              "enum": [true, false, "auto"]
            },
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          }
        },
        "source": { "$ref": "#/definitions/misc/source" },
        "outputs": {
          "description": "Execution, display, or stream outputs.",
          "type": "array",
          "items": { "$ref": "#/definitions/output" }
        },
        "execution_count": {
          "description": "The code cell's prompt number. Will be null if the cell has not been run.",
          "type": ["integer", "null"],
          "minimum": 0
        }
      }
    },

    "unrecognized_cell": {
      "description": "Unrecognized cell from a future minor-revision to the notebook format.",
      "type": "object",
      "additionalProperties": true,
      "required": ["cell_type", "metadata"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "not": {
            "enum": ["markdown", "code", "raw"]
          }
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "properties": {
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          },
          "additionalProperties": true
        }
      }
    },

    "output": {
      "type": "object",
      "oneOf": [
        { "$ref": "#/definitions/execute_result" },
        { "$ref": "#/definitions/display_data" },
        { "$ref": "#/definitions/stream" },
        { "$ref": "#/definitions/error" }
      ]
    },

    "execute_result": {
      "description": "Result of executing a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "data", "metadata", "execution_count"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["execute_result"]
        },
        "execution_count": {
          "description": "A result's prompt number.",
          "type": ["integer", "null"],
          "minimum": 0
        },
        "data": { "$ref": "#/definitions/misc/mimebundle" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      }
    },

    "display_data": {
      "description": "Data displayed as a result of code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "data", "metadata"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["display_data"]
        },
        "data": { "$ref": "#/definitions/misc/mimebundle" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      }
    },

    "stream": {
      "description": "Stream output from a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "name", "text"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["stream"]
        },
        "name": {
          "description": "The name of the stream (stdout, stderr).",
          "type": "string"
        },
        "text": {
          "description": "The stream's text output, represented as an array of strings.",
          "$ref": "#/definitions/misc/multiline_string"
        }
      }
    },

    "error": {
      "description": "Output of an error that occurred during code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "ename", "evalue", "traceback"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["error"]
        },
        "ename": {
          "description": "The name of the error.",
          "type": "string"
        },
        "evalue": {
          "description": "The value, or message, of the error.",
          "type": "string"
        },
        "traceback": {
          "description": "The error's traceback, represented as an array of strings.",
          "type": "array",
          "items": { "type": "string" }
        }
      }
    },

    "unrecognized_output": {
      "description": "Unrecognized output from a future minor-revision to the notebook format.",
      "type": "object",
      "additionalProperties": true,
      "required": ["output_type"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "not": {
            "enum": ["execute_result", "display_data", "stream", "error"]
          }
        }
      }
    },

    "misc": {
      "metadata_name": {
        "description": "The cell's name. If present, must be a non-empty string.",
        "type": "string",
        "pattern": "^.+$"
      },
      "metadata_tags": {
        "description": "The cell's tags. Tags must be unique, and must not contain commas.",
        "type": "array",
        "uniqueItems": true,
        "items": {
          "type": "string",
          "pattern": "^[^,]+$"
        }
      },
      "attachments": {
        "description": "Media attachments (e.g. inline images), stored as mimebundle keyed by filename.",
        "type": "object",
        "patternProperties": {
          ".*": {
            "description": "The attachment's data stored as a mimebundle.",
            "$ref": "#/definitions/misc/mimebundle"
          }
        }
      },
      "source": {
        "description": "Contents of the cell, represented as an array of lines.",
        "$ref": "#/definitions/misc/multiline_string"
      },
      "execution_count": {
        "description": "The code cell's prompt number. Will be null if the cell has not been run.",
        "type": ["integer", "null"],
        "minimum": 0
      },
      "mimebundle": {
        "description": "A mime-type keyed dictionary of data",
        "type": "object",
        "additionalProperties": {
          "description": "mimetype output (e.g. text/plain), represented as either an array of strings or a string.",
          "$ref": "#/definitions/misc/multiline_string"
        },
        "patternProperties": {
          "^application/(.*\\+)?json$": {
            "description": "Mimetypes with JSON output, can be any type"
          }
        }
      },
      "output_metadata": {
        "description": "Cell output metadata.",
        "type": "object",
        "additionalProperties": true
      },
      "multiline_string": {
        "oneOf": [
          { "type": "string" },
          {
            "type": "array",
            "items": { "type": "string" }
          }
        ]
      }
    }
  }
}
nbformat-5.9.1/nbformat/v4/nbformat.v4.1.schema.json000066400000000000000000000300341445275403000221340ustar00rootroot00000000000000{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "description": "IPython Notebook v4.1 JSON schema.",
  "type": "object",
  "additionalProperties": false,
  "required": ["metadata", "nbformat_minor", "nbformat", "cells"],
  "properties": {
    "metadata": {
      "description": "Notebook root-level metadata.",
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "kernelspec": {
          "description": "Kernel information.",
          "type": "object",
          "required": ["name", "display_name"],
          "properties": {
            "name": {
              "description": "Name of the kernel specification.",
              "type": "string"
            },
            "display_name": {
              "description": "Name to display in UI.",
              "type": "string"
            }
          }
        },
        "language_info": {
          "description": "Kernel information.",
          "type": "object",
          "required": ["name"],
          "properties": {
            "name": {
              "description": "The programming language which this kernel runs.",
              "type": "string"
            },
            "codemirror_mode": {
              "description": "The codemirror mode to use for code in this language.",
              "oneOf": [{ "type": "string" }, { "type": "object" }]
            },
            "file_extension": {
              "description": "The file extension for files in this language.",
              "type": "string"
            },
            "mimetype": {
              "description": "The mimetype corresponding to files in this language.",
              "type": "string"
            },
            "pygments_lexer": {
              "description": "The pygments lexer to use for code in this language.",
              "type": "string"
            }
          }
        },
        "orig_nbformat": {
          "description": "Original notebook format (major number) before converting the notebook between versions. This should never be written to a file.",
          "type": "integer",
          "minimum": 1
        }
      }
    },
    "nbformat_minor": {
      "description": "Notebook format (minor number). Incremented for backward compatible changes to the notebook format.",
      "type": "integer",
      "minimum": 1
    },
    "nbformat": {
      "description": "Notebook format (major number). Incremented between backwards incompatible changes to the notebook format.",
      "type": "integer",
      "minimum": 4,
      "maximum": 4
    },
    "cells": {
      "description": "Array of cells of the current notebook.",
      "type": "array",
      "items": { "$ref": "#/definitions/cell" }
    }
  },

  "definitions": {
    "cell": {
      "type": "object",
      "oneOf": [
        { "$ref": "#/definitions/raw_cell" },
        { "$ref": "#/definitions/markdown_cell" },
        { "$ref": "#/definitions/code_cell" }
      ]
    },

    "raw_cell": {
      "description": "Notebook raw nbconvert cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "metadata", "source"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["raw"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "format": {
              "description": "Raw cell metadata format for nbconvert.",
              "type": "string"
            },
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          }
        },
        "attachments": { "$ref": "#/definitions/misc/attachments" },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "markdown_cell": {
      "description": "Notebook markdown cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "metadata", "source"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["markdown"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "properties": {
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          },
          "additionalProperties": true
        },
        "attachments": { "$ref": "#/definitions/misc/attachments" },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "code_cell": {
      "description": "Notebook code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "cell_type",
        "metadata",
        "source",
        "outputs",
        "execution_count"
      ],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["code"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "collapsed": {
              "description": "Whether the cell is collapsed/expanded.",
              "type": "boolean"
            },
            "scrolled": {
              "description": "Whether the cell's output is scrolled, unscrolled, or autoscrolled.",
              "enum": [true, false, "auto"]
            },
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          }
        },
        "source": { "$ref": "#/definitions/misc/source" },
        "outputs": {
          "description": "Execution, display, or stream outputs.",
          "type": "array",
          "items": { "$ref": "#/definitions/output" }
        },
        "execution_count": {
          "description": "The code cell's prompt number. Will be null if the cell has not been run.",
          "type": ["integer", "null"],
          "minimum": 0
        }
      }
    },

    "unrecognized_cell": {
      "description": "Unrecognized cell from a future minor-revision to the notebook format.",
      "type": "object",
      "additionalProperties": true,
      "required": ["cell_type", "metadata"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "not": {
            "enum": ["markdown", "code", "raw"]
          }
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "properties": {
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          },
          "additionalProperties": true
        }
      }
    },

    "output": {
      "type": "object",
      "oneOf": [
        { "$ref": "#/definitions/execute_result" },
        { "$ref": "#/definitions/display_data" },
        { "$ref": "#/definitions/stream" },
        { "$ref": "#/definitions/error" }
      ]
    },

    "execute_result": {
      "description": "Result of executing a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "data", "metadata", "execution_count"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["execute_result"]
        },
        "execution_count": {
          "description": "A result's prompt number.",
          "type": ["integer", "null"],
          "minimum": 0
        },
        "data": { "$ref": "#/definitions/misc/mimebundle" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      }
    },

    "display_data": {
      "description": "Data displayed as a result of code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "data", "metadata"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["display_data"]
        },
        "data": { "$ref": "#/definitions/misc/mimebundle" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      }
    },

    "stream": {
      "description": "Stream output from a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "name", "text"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["stream"]
        },
        "name": {
          "description": "The name of the stream (stdout, stderr).",
          "type": "string"
        },
        "text": {
          "description": "The stream's text output, represented as an array of strings.",
          "$ref": "#/definitions/misc/multiline_string"
        }
      }
    },

    "error": {
      "description": "Output of an error that occurred during code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "ename", "evalue", "traceback"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["error"]
        },
        "ename": {
          "description": "The name of the error.",
          "type": "string"
        },
        "evalue": {
          "description": "The value, or message, of the error.",
          "type": "string"
        },
        "traceback": {
          "description": "The error's traceback, represented as an array of strings.",
          "type": "array",
          "items": { "type": "string" }
        }
      }
    },

    "unrecognized_output": {
      "description": "Unrecognized output from a future minor-revision to the notebook format.",
      "type": "object",
      "additionalProperties": true,
      "required": ["output_type"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "not": {
            "enum": ["execute_result", "display_data", "stream", "error"]
          }
        }
      }
    },

    "misc": {
      "metadata_name": {
        "description": "The cell's name. If present, must be a non-empty string.",
        "type": "string",
        "pattern": "^.+$"
      },
      "metadata_tags": {
        "description": "The cell's tags. Tags must be unique, and must not contain commas.",
        "type": "array",
        "uniqueItems": true,
        "items": {
          "type": "string",
          "pattern": "^[^,]+$"
        }
      },
      "attachments": {
        "description": "Media attachments (e.g. inline images), stored as mimebundle keyed by filename.",
        "type": "object",
        "patternProperties": {
          ".*": {
            "description": "The attachment's data stored as a mimebundle.",
            "$ref": "#/definitions/misc/mimebundle"
          }
        }
      },
      "source": {
        "description": "Contents of the cell, represented as an array of lines.",
        "$ref": "#/definitions/misc/multiline_string"
      },
      "execution_count": {
        "description": "The code cell's prompt number. Will be null if the cell has not been run.",
        "type": ["integer", "null"],
        "minimum": 0
      },
      "mimebundle": {
        "description": "A mime-type keyed dictionary of data",
        "type": "object",
        "additionalProperties": {
          "description": "mimetype output (e.g. text/plain), represented as either an array of strings or a string.",
          "$ref": "#/definitions/misc/multiline_string"
        },
        "patternProperties": {
          "^application/(.*\\+)?json$": {
            "description": "Mimetypes with JSON output, can be any type"
          }
        }
      },
      "output_metadata": {
        "description": "Cell output metadata.",
        "type": "object",
        "additionalProperties": true
      },
      "multiline_string": {
        "oneOf": [
          { "type": "string" },
          {
            "type": "array",
            "items": { "type": "string" }
          }
        ]
      }
    }
  }
}
nbformat-5.9.1/nbformat/v4/nbformat.v4.2.schema.json000066400000000000000000000310461445275403000221410ustar00rootroot00000000000000{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "description": "Jupyter Notebook v4.2 JSON schema.",
  "type": "object",
  "additionalProperties": false,
  "required": ["metadata", "nbformat_minor", "nbformat", "cells"],
  "properties": {
    "metadata": {
      "description": "Notebook root-level metadata.",
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "kernelspec": {
          "description": "Kernel information.",
          "type": "object",
          "required": ["name", "display_name"],
          "properties": {
            "name": {
              "description": "Name of the kernel specification.",
              "type": "string"
            },
            "display_name": {
              "description": "Name to display in UI.",
              "type": "string"
            }
          }
        },
        "language_info": {
          "description": "Kernel information.",
          "type": "object",
          "required": ["name"],
          "properties": {
            "name": {
              "description": "The programming language which this kernel runs.",
              "type": "string"
            },
            "codemirror_mode": {
              "description": "The codemirror mode to use for code in this language.",
              "oneOf": [{ "type": "string" }, { "type": "object" }]
            },
            "file_extension": {
              "description": "The file extension for files in this language.",
              "type": "string"
            },
            "mimetype": {
              "description": "The mimetype corresponding to files in this language.",
              "type": "string"
            },
            "pygments_lexer": {
              "description": "The pygments lexer to use for code in this language.",
              "type": "string"
            }
          }
        },
        "orig_nbformat": {
          "description": "Original notebook format (major number) before converting the notebook between versions. This should never be written to a file.",
          "type": "integer",
          "minimum": 1
        },
        "title": {
          "description": "The title of the notebook document",
          "type": "string"
        },
        "authors": {
          "description": "The author(s) of the notebook document",
          "type": "array",
          "item": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              }
            },
            "additionalProperties": true
          }
        }
      }
    },
    "nbformat_minor": {
      "description": "Notebook format (minor number). Incremented for backward compatible changes to the notebook format.",
      "type": "integer",
      "minimum": 2
    },
    "nbformat": {
      "description": "Notebook format (major number). Incremented between backwards incompatible changes to the notebook format.",
      "type": "integer",
      "minimum": 4,
      "maximum": 4
    },
    "cells": {
      "description": "Array of cells of the current notebook.",
      "type": "array",
      "items": { "$ref": "#/definitions/cell" }
    }
  },

  "definitions": {
    "cell": {
      "type": "object",
      "oneOf": [
        { "$ref": "#/definitions/raw_cell" },
        { "$ref": "#/definitions/markdown_cell" },
        { "$ref": "#/definitions/code_cell" }
      ]
    },

    "raw_cell": {
      "description": "Notebook raw nbconvert cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "metadata", "source"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["raw"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "format": {
              "description": "Raw cell metadata format for nbconvert.",
              "type": "string"
            },
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          }
        },
        "attachments": { "$ref": "#/definitions/misc/attachments" },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "markdown_cell": {
      "description": "Notebook markdown cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "metadata", "source"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["markdown"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "properties": {
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          },
          "additionalProperties": true
        },
        "attachments": { "$ref": "#/definitions/misc/attachments" },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "code_cell": {
      "description": "Notebook code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "cell_type",
        "metadata",
        "source",
        "outputs",
        "execution_count"
      ],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["code"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "collapsed": {
              "description": "Whether the cell is collapsed/expanded.",
              "type": "boolean"
            },
            "scrolled": {
              "description": "Whether the cell's output is scrolled, unscrolled, or autoscrolled.",
              "enum": [true, false, "auto"]
            },
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          }
        },
        "source": { "$ref": "#/definitions/misc/source" },
        "outputs": {
          "description": "Execution, display, or stream outputs.",
          "type": "array",
          "items": { "$ref": "#/definitions/output" }
        },
        "execution_count": {
          "description": "The code cell's prompt number. Will be null if the cell has not been run.",
          "type": ["integer", "null"],
          "minimum": 0
        }
      }
    },

    "unrecognized_cell": {
      "description": "Unrecognized cell from a future minor-revision to the notebook format.",
      "type": "object",
      "additionalProperties": true,
      "required": ["cell_type", "metadata"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "not": {
            "enum": ["markdown", "code", "raw"]
          }
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "properties": {
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          },
          "additionalProperties": true
        }
      }
    },

    "output": {
      "type": "object",
      "oneOf": [
        { "$ref": "#/definitions/execute_result" },
        { "$ref": "#/definitions/display_data" },
        { "$ref": "#/definitions/stream" },
        { "$ref": "#/definitions/error" }
      ]
    },

    "execute_result": {
      "description": "Result of executing a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "data", "metadata", "execution_count"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["execute_result"]
        },
        "execution_count": {
          "description": "A result's prompt number.",
          "type": ["integer", "null"],
          "minimum": 0
        },
        "data": { "$ref": "#/definitions/misc/mimebundle" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      }
    },

    "display_data": {
      "description": "Data displayed as a result of code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "data", "metadata"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["display_data"]
        },
        "data": { "$ref": "#/definitions/misc/mimebundle" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      }
    },

    "stream": {
      "description": "Stream output from a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "name", "text"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["stream"]
        },
        "name": {
          "description": "The name of the stream (stdout, stderr).",
          "type": "string"
        },
        "text": {
          "description": "The stream's text output, represented as an array of strings.",
          "$ref": "#/definitions/misc/multiline_string"
        }
      }
    },

    "error": {
      "description": "Output of an error that occurred during code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "ename", "evalue", "traceback"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["error"]
        },
        "ename": {
          "description": "The name of the error.",
          "type": "string"
        },
        "evalue": {
          "description": "The value, or message, of the error.",
          "type": "string"
        },
        "traceback": {
          "description": "The error's traceback, represented as an array of strings.",
          "type": "array",
          "items": { "type": "string" }
        }
      }
    },

    "unrecognized_output": {
      "description": "Unrecognized output from a future minor-revision to the notebook format.",
      "type": "object",
      "additionalProperties": true,
      "required": ["output_type"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "not": {
            "enum": ["execute_result", "display_data", "stream", "error"]
          }
        }
      }
    },

    "misc": {
      "metadata_name": {
        "description": "The cell's name. If present, must be a non-empty string. Must be unique across all the cells of a given notebook.",
        "type": "string",
        "pattern": "^.+$"
      },
      "metadata_tags": {
        "description": "The cell's tags. Tags must be unique, and must not contain commas.",
        "type": "array",
        "uniqueItems": true,
        "items": {
          "type": "string",
          "pattern": "^[^,]+$"
        }
      },
      "attachments": {
        "description": "Media attachments (e.g. inline images), stored as mimebundle keyed by filename.",
        "type": "object",
        "patternProperties": {
          ".*": {
            "description": "The attachment's data stored as a mimebundle.",
            "$ref": "#/definitions/misc/mimebundle"
          }
        }
      },
      "source": {
        "description": "Contents of the cell, represented as an array of lines.",
        "$ref": "#/definitions/misc/multiline_string"
      },
      "execution_count": {
        "description": "The code cell's prompt number. Will be null if the cell has not been run.",
        "type": ["integer", "null"],
        "minimum": 0
      },
      "mimebundle": {
        "description": "A mime-type keyed dictionary of data",
        "type": "object",
        "additionalProperties": {
          "description": "mimetype output (e.g. text/plain), represented as either an array of strings or a string.",
          "$ref": "#/definitions/misc/multiline_string"
        },
        "patternProperties": {
          "^application/(.*\\+)?json$": {
            "description": "Mimetypes with JSON output, can be any type"
          }
        }
      },
      "output_metadata": {
        "description": "Cell output metadata.",
        "type": "object",
        "additionalProperties": true
      },
      "multiline_string": {
        "oneOf": [
          { "type": "string" },
          {
            "type": "array",
            "items": { "type": "string" }
          }
        ]
      }
    }
  }
}
nbformat-5.9.1/nbformat/v4/nbformat.v4.3.schema.json000066400000000000000000000332601445275403000221420ustar00rootroot00000000000000{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "description": "Jupyter Notebook v4.3 JSON schema.",
  "type": "object",
  "additionalProperties": false,
  "required": ["metadata", "nbformat_minor", "nbformat", "cells"],
  "properties": {
    "metadata": {
      "description": "Notebook root-level metadata.",
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "kernelspec": {
          "description": "Kernel information.",
          "type": "object",
          "required": ["name", "display_name"],
          "properties": {
            "name": {
              "description": "Name of the kernel specification.",
              "type": "string"
            },
            "display_name": {
              "description": "Name to display in UI.",
              "type": "string"
            }
          }
        },
        "language_info": {
          "description": "Kernel information.",
          "type": "object",
          "required": ["name"],
          "properties": {
            "name": {
              "description": "The programming language which this kernel runs.",
              "type": "string"
            },
            "codemirror_mode": {
              "description": "The codemirror mode to use for code in this language.",
              "oneOf": [{ "type": "string" }, { "type": "object" }]
            },
            "file_extension": {
              "description": "The file extension for files in this language.",
              "type": "string"
            },
            "mimetype": {
              "description": "The mimetype corresponding to files in this language.",
              "type": "string"
            },
            "pygments_lexer": {
              "description": "The pygments lexer to use for code in this language.",
              "type": "string"
            }
          }
        },
        "orig_nbformat": {
          "description": "Original notebook format (major number) before converting the notebook between versions. This should never be written to a file.",
          "type": "integer",
          "minimum": 1
        },
        "title": {
          "description": "The title of the notebook document",
          "type": "string"
        },
        "authors": {
          "description": "The author(s) of the notebook document",
          "type": "array",
          "item": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              }
            },
            "additionalProperties": true
          }
        }
      }
    },
    "nbformat_minor": {
      "description": "Notebook format (minor number). Incremented for backward compatible changes to the notebook format.",
      "type": "integer",
      "minimum": 3
    },
    "nbformat": {
      "description": "Notebook format (major number). Incremented between backwards incompatible changes to the notebook format.",
      "type": "integer",
      "minimum": 4,
      "maximum": 4
    },
    "cells": {
      "description": "Array of cells of the current notebook.",
      "type": "array",
      "items": { "$ref": "#/definitions/cell" }
    }
  },

  "definitions": {
    "cell": {
      "type": "object",
      "oneOf": [
        { "$ref": "#/definitions/raw_cell" },
        { "$ref": "#/definitions/markdown_cell" },
        { "$ref": "#/definitions/code_cell" }
      ]
    },

    "raw_cell": {
      "description": "Notebook raw nbconvert cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "metadata", "source"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["raw"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "format": {
              "description": "Raw cell metadata format for nbconvert.",
              "type": "string"
            },
            "jupyter": {
              "description": "Official Jupyter Metadata for Raw Cells",
              "type": "object",
              "additionalProperties": true,
              "source_hidden": {
                "description": "Whether the source is hidden.",
                "type": "boolean"
              }
            },
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          }
        },
        "attachments": { "$ref": "#/definitions/misc/attachments" },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "markdown_cell": {
      "description": "Notebook markdown cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "metadata", "source"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["markdown"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "properties": {
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" },
            "jupyter": {
              "description": "Official Jupyter Metadata for Markdown Cells",
              "type": "object",
              "additionalProperties": true,
              "source_hidden": {
                "description": "Whether the source is hidden.",
                "type": "boolean"
              }
            }
          },
          "additionalProperties": true
        },
        "attachments": { "$ref": "#/definitions/misc/attachments" },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "code_cell": {
      "description": "Notebook code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "cell_type",
        "metadata",
        "source",
        "outputs",
        "execution_count"
      ],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["code"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "jupyter": {
              "description": "Official Jupyter Metadata for Code Cells",
              "type": "object",
              "additionalProperties": true,
              "source_hidden": {
                "description": "Whether the source is hidden.",
                "type": "boolean"
              },
              "outputs_hidden": {
                "description": "Whether the outputs are hidden.",
                "type": "boolean"
              }
            },
            "collapsed": {
              "description": "Whether the cell is collapsed/expanded.",
              "type": "boolean"
            },
            "scrolled": {
              "description": "Whether the cell's output is scrolled, unscrolled, or autoscrolled.",
              "enum": [true, false, "auto"]
            },
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          }
        },
        "source": { "$ref": "#/definitions/misc/source" },
        "outputs": {
          "description": "Execution, display, or stream outputs.",
          "type": "array",
          "items": { "$ref": "#/definitions/output" }
        },
        "execution_count": {
          "description": "The code cell's prompt number. Will be null if the cell has not been run.",
          "type": ["integer", "null"],
          "minimum": 0
        }
      }
    },

    "unrecognized_cell": {
      "description": "Unrecognized cell from a future minor-revision to the notebook format.",
      "type": "object",
      "additionalProperties": true,
      "required": ["cell_type", "metadata"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "not": {
            "enum": ["markdown", "code", "raw"]
          }
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "properties": {
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          },
          "additionalProperties": true
        }
      }
    },

    "output": {
      "type": "object",
      "oneOf": [
        { "$ref": "#/definitions/execute_result" },
        { "$ref": "#/definitions/display_data" },
        { "$ref": "#/definitions/stream" },
        { "$ref": "#/definitions/error" }
      ]
    },

    "execute_result": {
      "description": "Result of executing a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "data", "metadata", "execution_count"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["execute_result"]
        },
        "execution_count": {
          "description": "A result's prompt number.",
          "type": ["integer", "null"],
          "minimum": 0
        },
        "data": { "$ref": "#/definitions/misc/mimebundle" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      }
    },

    "display_data": {
      "description": "Data displayed as a result of code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "data", "metadata"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["display_data"]
        },
        "data": { "$ref": "#/definitions/misc/mimebundle" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      }
    },

    "stream": {
      "description": "Stream output from a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "name", "text"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["stream"]
        },
        "name": {
          "description": "The name of the stream (stdout, stderr).",
          "type": "string"
        },
        "text": {
          "description": "The stream's text output, represented as an array of strings.",
          "$ref": "#/definitions/misc/multiline_string"
        }
      }
    },

    "error": {
      "description": "Output of an error that occurred during code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "ename", "evalue", "traceback"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["error"]
        },
        "ename": {
          "description": "The name of the error.",
          "type": "string"
        },
        "evalue": {
          "description": "The value, or message, of the error.",
          "type": "string"
        },
        "traceback": {
          "description": "The error's traceback, represented as an array of strings.",
          "type": "array",
          "items": { "type": "string" }
        }
      }
    },

    "unrecognized_output": {
      "description": "Unrecognized output from a future minor-revision to the notebook format.",
      "type": "object",
      "additionalProperties": true,
      "required": ["output_type"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "not": {
            "enum": ["execute_result", "display_data", "stream", "error"]
          }
        }
      }
    },

    "misc": {
      "metadata_name": {
        "description": "The cell's name. If present, must be a non-empty string. Must be unique across all the cells of a given notebook.",
        "type": "string",
        "pattern": "^.+$"
      },
      "metadata_tags": {
        "description": "The cell's tags. Tags must be unique, and must not contain commas.",
        "type": "array",
        "uniqueItems": true,
        "items": {
          "type": "string",
          "pattern": "^[^,]+$"
        }
      },
      "attachments": {
        "description": "Media attachments (e.g. inline images), stored as mimebundle keyed by filename.",
        "type": "object",
        "patternProperties": {
          ".*": {
            "description": "The attachment's data stored as a mimebundle.",
            "$ref": "#/definitions/misc/mimebundle"
          }
        }
      },
      "source": {
        "description": "Contents of the cell, represented as an array of lines.",
        "$ref": "#/definitions/misc/multiline_string"
      },
      "execution_count": {
        "description": "The code cell's prompt number. Will be null if the cell has not been run.",
        "type": ["integer", "null"],
        "minimum": 0
      },
      "mimebundle": {
        "description": "A mime-type keyed dictionary of data",
        "type": "object",
        "additionalProperties": {
          "description": "mimetype output (e.g. text/plain), represented as either an array of strings or a string.",
          "$ref": "#/definitions/misc/multiline_string"
        },
        "patternProperties": {
          "^application/(.*\\+)?json$": {
            "description": "Mimetypes with JSON output, can be any type"
          }
        }
      },
      "output_metadata": {
        "description": "Cell output metadata.",
        "type": "object",
        "additionalProperties": true
      },
      "multiline_string": {
        "oneOf": [
          { "type": "string" },
          {
            "type": "array",
            "items": { "type": "string" }
          }
        ]
      }
    }
  }
}
nbformat-5.9.1/nbformat/v4/nbformat.v4.4.schema.json000066400000000000000000000365271445275403000221540ustar00rootroot00000000000000{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "description": "Jupyter Notebook v4.4 JSON schema.",
  "type": "object",
  "additionalProperties": false,
  "required": ["metadata", "nbformat_minor", "nbformat", "cells"],
  "properties": {
    "metadata": {
      "description": "Notebook root-level metadata.",
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "kernelspec": {
          "description": "Kernel information.",
          "type": "object",
          "required": ["name", "display_name"],
          "properties": {
            "name": {
              "description": "Name of the kernel specification.",
              "type": "string"
            },
            "display_name": {
              "description": "Name to display in UI.",
              "type": "string"
            }
          }
        },
        "language_info": {
          "description": "Kernel information.",
          "type": "object",
          "required": ["name"],
          "properties": {
            "name": {
              "description": "The programming language which this kernel runs.",
              "type": "string"
            },
            "codemirror_mode": {
              "description": "The codemirror mode to use for code in this language.",
              "oneOf": [{ "type": "string" }, { "type": "object" }]
            },
            "file_extension": {
              "description": "The file extension for files in this language.",
              "type": "string"
            },
            "mimetype": {
              "description": "The mimetype corresponding to files in this language.",
              "type": "string"
            },
            "pygments_lexer": {
              "description": "The pygments lexer to use for code in this language.",
              "type": "string"
            }
          }
        },
        "orig_nbformat": {
          "description": "Original notebook format (major number) before converting the notebook between versions. This should never be written to a file.",
          "type": "integer",
          "minimum": 1
        },
        "title": {
          "description": "The title of the notebook document",
          "type": "string"
        },
        "authors": {
          "description": "The author(s) of the notebook document",
          "type": "array",
          "item": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              }
            },
            "additionalProperties": true
          }
        }
      }
    },
    "nbformat_minor": {
      "description": "Notebook format (minor number). Incremented for backward compatible changes to the notebook format.",
      "type": "integer",
      "minimum": 4
    },
    "nbformat": {
      "description": "Notebook format (major number). Incremented between backwards incompatible changes to the notebook format.",
      "type": "integer",
      "minimum": 4,
      "maximum": 4
    },
    "cells": {
      "description": "Array of cells of the current notebook.",
      "type": "array",
      "items": { "$ref": "#/definitions/cell" }
    }
  },

  "definitions": {
    "cell": {
      "type": "object",
      "oneOf": [
        { "$ref": "#/definitions/raw_cell" },
        { "$ref": "#/definitions/markdown_cell" },
        { "$ref": "#/definitions/code_cell" }
      ]
    },

    "raw_cell": {
      "description": "Notebook raw nbconvert cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "metadata", "source"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["raw"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "format": {
              "description": "Raw cell metadata format for nbconvert.",
              "type": "string"
            },
            "jupyter": {
              "description": "Official Jupyter Metadata for Raw Cells",
              "type": "object",
              "additionalProperties": true,
              "source_hidden": {
                "description": "Whether the source is hidden.",
                "type": "boolean"
              }
            },
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          }
        },
        "attachments": { "$ref": "#/definitions/misc/attachments" },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "markdown_cell": {
      "description": "Notebook markdown cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "metadata", "source"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["markdown"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "properties": {
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" },
            "jupyter": {
              "description": "Official Jupyter Metadata for Markdown Cells",
              "type": "object",
              "additionalProperties": true,
              "source_hidden": {
                "description": "Whether the source is hidden.",
                "type": "boolean"
              }
            }
          },
          "additionalProperties": true
        },
        "attachments": { "$ref": "#/definitions/misc/attachments" },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "code_cell": {
      "description": "Notebook code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "cell_type",
        "metadata",
        "source",
        "outputs",
        "execution_count"
      ],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["code"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "jupyter": {
              "description": "Official Jupyter Metadata for Code Cells",
              "type": "object",
              "additionalProperties": true,
              "source_hidden": {
                "description": "Whether the source is hidden.",
                "type": "boolean"
              },
              "outputs_hidden": {
                "description": "Whether the outputs are hidden.",
                "type": "boolean"
              }
            },
            "execution": {
              "description": "Execution time for the code in the cell. This tracks time at which messages are received from iopub or shell channels",
              "type": "object",
              "properties": {
                "iopub.execute_input": {
                  "description": "header.date (in ISO 8601 format) of iopub channel's execute_input message. It indicates the time at which the kernel broadcasts an execute_input message to connected frontends",
                  "type": "string"
                },
                "iopub.status.busy": {
                  "description": "header.date (in ISO 8601 format) of iopub channel's kernel status message when the status is 'busy'",
                  "type": "string"
                },
                "shell.execute_reply": {
                  "description": "header.date (in ISO 8601 format) of the shell channel's execute_reply message. It indicates the time at which the execute_reply message was created",
                  "type": "string"
                },
                "iopub.status.idle": {
                  "description": "header.date (in ISO 8601 format) of iopub channel's kernel status message when the status is 'idle'. It indicates the time at which kernel finished processing the associated request",
                  "type": "string"
                }
              },
              "additionalProperties": true,
              "patternProperties": {
                "^.*$": {
                  "type": "string"
                }
              }
            },
            "collapsed": {
              "description": "Whether the cell's output is collapsed/expanded.",
              "type": "boolean"
            },
            "scrolled": {
              "description": "Whether the cell's output is scrolled, unscrolled, or autoscrolled.",
              "enum": [true, false, "auto"]
            },
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          }
        },
        "source": { "$ref": "#/definitions/misc/source" },
        "outputs": {
          "description": "Execution, display, or stream outputs.",
          "type": "array",
          "items": { "$ref": "#/definitions/output" }
        },
        "execution_count": {
          "description": "The code cell's prompt number. Will be null if the cell has not been run.",
          "type": ["integer", "null"],
          "minimum": 0
        }
      }
    },

    "unrecognized_cell": {
      "description": "Unrecognized cell from a future minor-revision to the notebook format.",
      "type": "object",
      "additionalProperties": true,
      "required": ["cell_type", "metadata"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "not": {
            "enum": ["markdown", "code", "raw"]
          }
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "properties": {
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          },
          "additionalProperties": true
        }
      }
    },

    "output": {
      "type": "object",
      "oneOf": [
        { "$ref": "#/definitions/execute_result" },
        { "$ref": "#/definitions/display_data" },
        { "$ref": "#/definitions/stream" },
        { "$ref": "#/definitions/error" }
      ]
    },

    "execute_result": {
      "description": "Result of executing a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "data", "metadata", "execution_count"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["execute_result"]
        },
        "execution_count": {
          "description": "A result's prompt number.",
          "type": ["integer", "null"],
          "minimum": 0
        },
        "data": { "$ref": "#/definitions/misc/mimebundle" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      }
    },

    "display_data": {
      "description": "Data displayed as a result of code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "data", "metadata"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["display_data"]
        },
        "data": { "$ref": "#/definitions/misc/mimebundle" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      }
    },

    "stream": {
      "description": "Stream output from a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "name", "text"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["stream"]
        },
        "name": {
          "description": "The name of the stream (stdout, stderr).",
          "type": "string"
        },
        "text": {
          "description": "The stream's text output, represented as an array of strings.",
          "$ref": "#/definitions/misc/multiline_string"
        }
      }
    },

    "error": {
      "description": "Output of an error that occurred during code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "ename", "evalue", "traceback"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["error"]
        },
        "ename": {
          "description": "The name of the error.",
          "type": "string"
        },
        "evalue": {
          "description": "The value, or message, of the error.",
          "type": "string"
        },
        "traceback": {
          "description": "The error's traceback, represented as an array of strings.",
          "type": "array",
          "items": { "type": "string" }
        }
      }
    },

    "unrecognized_output": {
      "description": "Unrecognized output from a future minor-revision to the notebook format.",
      "type": "object",
      "additionalProperties": true,
      "required": ["output_type"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "not": {
            "enum": ["execute_result", "display_data", "stream", "error"]
          }
        }
      }
    },

    "misc": {
      "metadata_name": {
        "description": "The cell's name. If present, must be a non-empty string. Cell names are expected to be unique across all the cells in a given notebook. This criterion cannot be checked by the json schema and must be established by an additional check.",
        "type": "string",
        "pattern": "^.+$"
      },
      "metadata_tags": {
        "description": "The cell's tags. Tags must be unique, and must not contain commas.",
        "type": "array",
        "uniqueItems": true,
        "items": {
          "type": "string",
          "pattern": "^[^,]+$"
        }
      },
      "attachments": {
        "description": "Media attachments (e.g. inline images), stored as mimebundle keyed by filename.",
        "type": "object",
        "patternProperties": {
          ".*": {
            "description": "The attachment's data stored as a mimebundle.",
            "$ref": "#/definitions/misc/mimebundle"
          }
        }
      },
      "source": {
        "description": "Contents of the cell, represented as an array of lines.",
        "$ref": "#/definitions/misc/multiline_string"
      },
      "execution_count": {
        "description": "The code cell's prompt number. Will be null if the cell has not been run.",
        "type": ["integer", "null"],
        "minimum": 0
      },
      "mimebundle": {
        "description": "A mime-type keyed dictionary of data",
        "type": "object",
        "additionalProperties": {
          "description": "mimetype output (e.g. text/plain), represented as either an array of strings or a string.",
          "$ref": "#/definitions/misc/multiline_string"
        },
        "patternProperties": {
          "^application/(.*\\+)?json$": {
            "description": "Mimetypes with JSON output, can be any type"
          }
        }
      },
      "output_metadata": {
        "description": "Cell output metadata.",
        "type": "object",
        "additionalProperties": true
      },
      "multiline_string": {
        "oneOf": [
          { "type": "string" },
          {
            "type": "array",
            "items": { "type": "string" }
          }
        ]
      }
    }
  }
}
nbformat-5.9.1/nbformat/v4/nbformat.v4.5.schema.json000066400000000000000000000373501445275403000221500ustar00rootroot00000000000000{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "description": "Jupyter Notebook v4.5 JSON schema.",
  "type": "object",
  "additionalProperties": false,
  "required": ["metadata", "nbformat_minor", "nbformat", "cells"],
  "properties": {
    "metadata": {
      "description": "Notebook root-level metadata.",
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "kernelspec": {
          "description": "Kernel information.",
          "type": "object",
          "required": ["name", "display_name"],
          "properties": {
            "name": {
              "description": "Name of the kernel specification.",
              "type": "string"
            },
            "display_name": {
              "description": "Name to display in UI.",
              "type": "string"
            }
          }
        },
        "language_info": {
          "description": "Kernel information.",
          "type": "object",
          "required": ["name"],
          "properties": {
            "name": {
              "description": "The programming language which this kernel runs.",
              "type": "string"
            },
            "codemirror_mode": {
              "description": "The codemirror mode to use for code in this language.",
              "oneOf": [{ "type": "string" }, { "type": "object" }]
            },
            "file_extension": {
              "description": "The file extension for files in this language.",
              "type": "string"
            },
            "mimetype": {
              "description": "The mimetype corresponding to files in this language.",
              "type": "string"
            },
            "pygments_lexer": {
              "description": "The pygments lexer to use for code in this language.",
              "type": "string"
            }
          }
        },
        "orig_nbformat": {
          "description": "Original notebook format (major number) before converting the notebook between versions. This should never be written to a file.",
          "type": "integer",
          "minimum": 1
        },
        "title": {
          "description": "The title of the notebook document",
          "type": "string"
        },
        "authors": {
          "description": "The author(s) of the notebook document",
          "type": "array",
          "item": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              }
            },
            "additionalProperties": true
          }
        }
      }
    },
    "nbformat_minor": {
      "description": "Notebook format (minor number). Incremented for backward compatible changes to the notebook format.",
      "type": "integer",
      "minimum": 5
    },
    "nbformat": {
      "description": "Notebook format (major number). Incremented between backwards incompatible changes to the notebook format.",
      "type": "integer",
      "minimum": 4,
      "maximum": 4
    },
    "cells": {
      "description": "Array of cells of the current notebook.",
      "type": "array",
      "items": { "$ref": "#/definitions/cell" }
    }
  },

  "definitions": {
    "cell_id": {
      "description": "A string field representing the identifier of this particular cell.",
      "type": "string",
      "pattern": "^[a-zA-Z0-9-_]+$",
      "minLength": 1,
      "maxLength": 64
    },

    "cell": {
      "type": "object",
      "oneOf": [
        { "$ref": "#/definitions/raw_cell" },
        { "$ref": "#/definitions/markdown_cell" },
        { "$ref": "#/definitions/code_cell" }
      ]
    },

    "raw_cell": {
      "description": "Notebook raw nbconvert cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "cell_type", "metadata", "source"],
      "properties": {
        "id": { "$ref": "#/definitions/cell_id" },
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["raw"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "format": {
              "description": "Raw cell metadata format for nbconvert.",
              "type": "string"
            },
            "jupyter": {
              "description": "Official Jupyter Metadata for Raw Cells",
              "type": "object",
              "additionalProperties": true,
              "source_hidden": {
                "description": "Whether the source is hidden.",
                "type": "boolean"
              }
            },
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          }
        },
        "attachments": { "$ref": "#/definitions/misc/attachments" },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "markdown_cell": {
      "description": "Notebook markdown cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "cell_type", "metadata", "source"],
      "properties": {
        "id": { "$ref": "#/definitions/cell_id" },
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["markdown"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "properties": {
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" },
            "jupyter": {
              "description": "Official Jupyter Metadata for Markdown Cells",
              "type": "object",
              "additionalProperties": true,
              "source_hidden": {
                "description": "Whether the source is hidden.",
                "type": "boolean"
              }
            }
          },
          "additionalProperties": true
        },
        "attachments": { "$ref": "#/definitions/misc/attachments" },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "code_cell": {
      "description": "Notebook code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "cell_type",
        "metadata",
        "source",
        "outputs",
        "execution_count"
      ],
      "properties": {
        "id": { "$ref": "#/definitions/cell_id" },
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["code"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "jupyter": {
              "description": "Official Jupyter Metadata for Code Cells",
              "type": "object",
              "additionalProperties": true,
              "source_hidden": {
                "description": "Whether the source is hidden.",
                "type": "boolean"
              },
              "outputs_hidden": {
                "description": "Whether the outputs are hidden.",
                "type": "boolean"
              }
            },
            "execution": {
              "description": "Execution time for the code in the cell. This tracks time at which messages are received from iopub or shell channels",
              "type": "object",
              "properties": {
                "iopub.execute_input": {
                  "description": "header.date (in ISO 8601 format) of iopub channel's execute_input message. It indicates the time at which the kernel broadcasts an execute_input message to connected frontends",
                  "type": "string"
                },
                "iopub.status.busy": {
                  "description": "header.date (in ISO 8601 format) of iopub channel's kernel status message when the status is 'busy'",
                  "type": "string"
                },
                "shell.execute_reply": {
                  "description": "header.date (in ISO 8601 format) of the shell channel's execute_reply message. It indicates the time at which the execute_reply message was created",
                  "type": "string"
                },
                "iopub.status.idle": {
                  "description": "header.date (in ISO 8601 format) of iopub channel's kernel status message when the status is 'idle'. It indicates the time at which kernel finished processing the associated request",
                  "type": "string"
                }
              },
              "additionalProperties": true,
              "patternProperties": {
                "^.*$": {
                  "type": "string"
                }
              }
            },
            "collapsed": {
              "description": "Whether the cell's output is collapsed/expanded.",
              "type": "boolean"
            },
            "scrolled": {
              "description": "Whether the cell's output is scrolled, unscrolled, or autoscrolled.",
              "enum": [true, false, "auto"]
            },
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          }
        },
        "source": { "$ref": "#/definitions/misc/source" },
        "outputs": {
          "description": "Execution, display, or stream outputs.",
          "type": "array",
          "items": { "$ref": "#/definitions/output" }
        },
        "execution_count": {
          "description": "The code cell's prompt number. Will be null if the cell has not been run.",
          "type": ["integer", "null"],
          "minimum": 0
        }
      }
    },

    "unrecognized_cell": {
      "description": "Unrecognized cell from a future minor-revision to the notebook format.",
      "type": "object",
      "additionalProperties": true,
      "required": ["cell_type", "metadata"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "not": {
            "enum": ["markdown", "code", "raw"]
          }
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "properties": {
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          },
          "additionalProperties": true
        }
      }
    },

    "output": {
      "type": "object",
      "oneOf": [
        { "$ref": "#/definitions/execute_result" },
        { "$ref": "#/definitions/display_data" },
        { "$ref": "#/definitions/stream" },
        { "$ref": "#/definitions/error" }
      ]
    },

    "execute_result": {
      "description": "Result of executing a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "data", "metadata", "execution_count"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["execute_result"]
        },
        "execution_count": {
          "description": "A result's prompt number.",
          "type": ["integer", "null"],
          "minimum": 0
        },
        "data": { "$ref": "#/definitions/misc/mimebundle" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      }
    },

    "display_data": {
      "description": "Data displayed as a result of code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "data", "metadata"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["display_data"]
        },
        "data": { "$ref": "#/definitions/misc/mimebundle" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      }
    },

    "stream": {
      "description": "Stream output from a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "name", "text"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["stream"]
        },
        "name": {
          "description": "The name of the stream (stdout, stderr).",
          "type": "string"
        },
        "text": {
          "description": "The stream's text output, represented as an array of strings.",
          "$ref": "#/definitions/misc/multiline_string"
        }
      }
    },

    "error": {
      "description": "Output of an error that occurred during code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "ename", "evalue", "traceback"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["error"]
        },
        "ename": {
          "description": "The name of the error.",
          "type": "string"
        },
        "evalue": {
          "description": "The value, or message, of the error.",
          "type": "string"
        },
        "traceback": {
          "description": "The error's traceback, represented as an array of strings.",
          "type": "array",
          "items": { "type": "string" }
        }
      }
    },

    "unrecognized_output": {
      "description": "Unrecognized output from a future minor-revision to the notebook format.",
      "type": "object",
      "additionalProperties": true,
      "required": ["output_type"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "not": {
            "enum": ["execute_result", "display_data", "stream", "error"]
          }
        }
      }
    },

    "misc": {
      "metadata_name": {
        "description": "The cell's name. If present, must be a non-empty string. Cell names are expected to be unique across all the cells in a given notebook. This criterion cannot be checked by the json schema and must be established by an additional check.",
        "type": "string",
        "pattern": "^.+$"
      },
      "metadata_tags": {
        "description": "The cell's tags. Tags must be unique, and must not contain commas.",
        "type": "array",
        "uniqueItems": true,
        "items": {
          "type": "string",
          "pattern": "^[^,]+$"
        }
      },
      "attachments": {
        "description": "Media attachments (e.g. inline images), stored as mimebundle keyed by filename.",
        "type": "object",
        "patternProperties": {
          ".*": {
            "description": "The attachment's data stored as a mimebundle.",
            "$ref": "#/definitions/misc/mimebundle"
          }
        }
      },
      "source": {
        "description": "Contents of the cell, represented as an array of lines.",
        "$ref": "#/definitions/misc/multiline_string"
      },
      "execution_count": {
        "description": "The code cell's prompt number. Will be null if the cell has not been run.",
        "type": ["integer", "null"],
        "minimum": 0
      },
      "mimebundle": {
        "description": "A mime-type keyed dictionary of data",
        "type": "object",
        "additionalProperties": {
          "description": "mimetype output (e.g. text/plain), represented as either an array of strings or a string.",
          "$ref": "#/definitions/misc/multiline_string"
        },
        "patternProperties": {
          "^application/(.*\\+)?json$": {
            "description": "Mimetypes with JSON output, can be any type"
          }
        }
      },
      "output_metadata": {
        "description": "Cell output metadata.",
        "type": "object",
        "additionalProperties": true
      },
      "multiline_string": {
        "oneOf": [
          { "type": "string" },
          {
            "type": "array",
            "items": { "type": "string" }
          }
        ]
      }
    }
  }
}
nbformat-5.9.1/nbformat/v4/nbformat.v4.schema.json000066400000000000000000000373501445275403000220050ustar00rootroot00000000000000{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "description": "Jupyter Notebook v4.5 JSON schema.",
  "type": "object",
  "additionalProperties": false,
  "required": ["metadata", "nbformat_minor", "nbformat", "cells"],
  "properties": {
    "metadata": {
      "description": "Notebook root-level metadata.",
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "kernelspec": {
          "description": "Kernel information.",
          "type": "object",
          "required": ["name", "display_name"],
          "properties": {
            "name": {
              "description": "Name of the kernel specification.",
              "type": "string"
            },
            "display_name": {
              "description": "Name to display in UI.",
              "type": "string"
            }
          }
        },
        "language_info": {
          "description": "Kernel information.",
          "type": "object",
          "required": ["name"],
          "properties": {
            "name": {
              "description": "The programming language which this kernel runs.",
              "type": "string"
            },
            "codemirror_mode": {
              "description": "The codemirror mode to use for code in this language.",
              "oneOf": [{ "type": "string" }, { "type": "object" }]
            },
            "file_extension": {
              "description": "The file extension for files in this language.",
              "type": "string"
            },
            "mimetype": {
              "description": "The mimetype corresponding to files in this language.",
              "type": "string"
            },
            "pygments_lexer": {
              "description": "The pygments lexer to use for code in this language.",
              "type": "string"
            }
          }
        },
        "orig_nbformat": {
          "description": "Original notebook format (major number) before converting the notebook between versions. This should never be written to a file.",
          "type": "integer",
          "minimum": 1
        },
        "title": {
          "description": "The title of the notebook document",
          "type": "string"
        },
        "authors": {
          "description": "The author(s) of the notebook document",
          "type": "array",
          "item": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              }
            },
            "additionalProperties": true
          }
        }
      }
    },
    "nbformat_minor": {
      "description": "Notebook format (minor number). Incremented for backward compatible changes to the notebook format.",
      "type": "integer",
      "minimum": 5
    },
    "nbformat": {
      "description": "Notebook format (major number). Incremented between backwards incompatible changes to the notebook format.",
      "type": "integer",
      "minimum": 4,
      "maximum": 4
    },
    "cells": {
      "description": "Array of cells of the current notebook.",
      "type": "array",
      "items": { "$ref": "#/definitions/cell" }
    }
  },

  "definitions": {
    "cell_id": {
      "description": "A string field representing the identifier of this particular cell.",
      "type": "string",
      "pattern": "^[a-zA-Z0-9-_]+$",
      "minLength": 1,
      "maxLength": 64
    },

    "cell": {
      "type": "object",
      "oneOf": [
        { "$ref": "#/definitions/raw_cell" },
        { "$ref": "#/definitions/markdown_cell" },
        { "$ref": "#/definitions/code_cell" }
      ]
    },

    "raw_cell": {
      "description": "Notebook raw nbconvert cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "cell_type", "metadata", "source"],
      "properties": {
        "id": { "$ref": "#/definitions/cell_id" },
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["raw"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "format": {
              "description": "Raw cell metadata format for nbconvert.",
              "type": "string"
            },
            "jupyter": {
              "description": "Official Jupyter Metadata for Raw Cells",
              "type": "object",
              "additionalProperties": true,
              "source_hidden": {
                "description": "Whether the source is hidden.",
                "type": "boolean"
              }
            },
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          }
        },
        "attachments": { "$ref": "#/definitions/misc/attachments" },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "markdown_cell": {
      "description": "Notebook markdown cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "cell_type", "metadata", "source"],
      "properties": {
        "id": { "$ref": "#/definitions/cell_id" },
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["markdown"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "properties": {
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" },
            "jupyter": {
              "description": "Official Jupyter Metadata for Markdown Cells",
              "type": "object",
              "additionalProperties": true,
              "source_hidden": {
                "description": "Whether the source is hidden.",
                "type": "boolean"
              }
            }
          },
          "additionalProperties": true
        },
        "attachments": { "$ref": "#/definitions/misc/attachments" },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "code_cell": {
      "description": "Notebook code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "cell_type",
        "metadata",
        "source",
        "outputs",
        "execution_count"
      ],
      "properties": {
        "id": { "$ref": "#/definitions/cell_id" },
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["code"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "jupyter": {
              "description": "Official Jupyter Metadata for Code Cells",
              "type": "object",
              "additionalProperties": true,
              "source_hidden": {
                "description": "Whether the source is hidden.",
                "type": "boolean"
              },
              "outputs_hidden": {
                "description": "Whether the outputs are hidden.",
                "type": "boolean"
              }
            },
            "execution": {
              "description": "Execution time for the code in the cell. This tracks time at which messages are received from iopub or shell channels",
              "type": "object",
              "properties": {
                "iopub.execute_input": {
                  "description": "header.date (in ISO 8601 format) of iopub channel's execute_input message. It indicates the time at which the kernel broadcasts an execute_input message to connected frontends",
                  "type": "string"
                },
                "iopub.status.busy": {
                  "description": "header.date (in ISO 8601 format) of iopub channel's kernel status message when the status is 'busy'",
                  "type": "string"
                },
                "shell.execute_reply": {
                  "description": "header.date (in ISO 8601 format) of the shell channel's execute_reply message. It indicates the time at which the execute_reply message was created",
                  "type": "string"
                },
                "iopub.status.idle": {
                  "description": "header.date (in ISO 8601 format) of iopub channel's kernel status message when the status is 'idle'. It indicates the time at which kernel finished processing the associated request",
                  "type": "string"
                }
              },
              "additionalProperties": true,
              "patternProperties": {
                "^.*$": {
                  "type": "string"
                }
              }
            },
            "collapsed": {
              "description": "Whether the cell's output is collapsed/expanded.",
              "type": "boolean"
            },
            "scrolled": {
              "description": "Whether the cell's output is scrolled, unscrolled, or autoscrolled.",
              "enum": [true, false, "auto"]
            },
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          }
        },
        "source": { "$ref": "#/definitions/misc/source" },
        "outputs": {
          "description": "Execution, display, or stream outputs.",
          "type": "array",
          "items": { "$ref": "#/definitions/output" }
        },
        "execution_count": {
          "description": "The code cell's prompt number. Will be null if the cell has not been run.",
          "type": ["integer", "null"],
          "minimum": 0
        }
      }
    },

    "unrecognized_cell": {
      "description": "Unrecognized cell from a future minor-revision to the notebook format.",
      "type": "object",
      "additionalProperties": true,
      "required": ["cell_type", "metadata"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "not": {
            "enum": ["markdown", "code", "raw"]
          }
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "properties": {
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          },
          "additionalProperties": true
        }
      }
    },

    "output": {
      "type": "object",
      "oneOf": [
        { "$ref": "#/definitions/execute_result" },
        { "$ref": "#/definitions/display_data" },
        { "$ref": "#/definitions/stream" },
        { "$ref": "#/definitions/error" }
      ]
    },

    "execute_result": {
      "description": "Result of executing a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "data", "metadata", "execution_count"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["execute_result"]
        },
        "execution_count": {
          "description": "A result's prompt number.",
          "type": ["integer", "null"],
          "minimum": 0
        },
        "data": { "$ref": "#/definitions/misc/mimebundle" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      }
    },

    "display_data": {
      "description": "Data displayed as a result of code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "data", "metadata"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["display_data"]
        },
        "data": { "$ref": "#/definitions/misc/mimebundle" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      }
    },

    "stream": {
      "description": "Stream output from a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "name", "text"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["stream"]
        },
        "name": {
          "description": "The name of the stream (stdout, stderr).",
          "type": "string"
        },
        "text": {
          "description": "The stream's text output, represented as an array of strings.",
          "$ref": "#/definitions/misc/multiline_string"
        }
      }
    },

    "error": {
      "description": "Output of an error that occurred during code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "ename", "evalue", "traceback"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["error"]
        },
        "ename": {
          "description": "The name of the error.",
          "type": "string"
        },
        "evalue": {
          "description": "The value, or message, of the error.",
          "type": "string"
        },
        "traceback": {
          "description": "The error's traceback, represented as an array of strings.",
          "type": "array",
          "items": { "type": "string" }
        }
      }
    },

    "unrecognized_output": {
      "description": "Unrecognized output from a future minor-revision to the notebook format.",
      "type": "object",
      "additionalProperties": true,
      "required": ["output_type"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "not": {
            "enum": ["execute_result", "display_data", "stream", "error"]
          }
        }
      }
    },

    "misc": {
      "metadata_name": {
        "description": "The cell's name. If present, must be a non-empty string. Cell names are expected to be unique across all the cells in a given notebook. This criterion cannot be checked by the json schema and must be established by an additional check.",
        "type": "string",
        "pattern": "^.+$"
      },
      "metadata_tags": {
        "description": "The cell's tags. Tags must be unique, and must not contain commas.",
        "type": "array",
        "uniqueItems": true,
        "items": {
          "type": "string",
          "pattern": "^[^,]+$"
        }
      },
      "attachments": {
        "description": "Media attachments (e.g. inline images), stored as mimebundle keyed by filename.",
        "type": "object",
        "patternProperties": {
          ".*": {
            "description": "The attachment's data stored as a mimebundle.",
            "$ref": "#/definitions/misc/mimebundle"
          }
        }
      },
      "source": {
        "description": "Contents of the cell, represented as an array of lines.",
        "$ref": "#/definitions/misc/multiline_string"
      },
      "execution_count": {
        "description": "The code cell's prompt number. Will be null if the cell has not been run.",
        "type": ["integer", "null"],
        "minimum": 0
      },
      "mimebundle": {
        "description": "A mime-type keyed dictionary of data",
        "type": "object",
        "additionalProperties": {
          "description": "mimetype output (e.g. text/plain), represented as either an array of strings or a string.",
          "$ref": "#/definitions/misc/multiline_string"
        },
        "patternProperties": {
          "^application/(.*\\+)?json$": {
            "description": "Mimetypes with JSON output, can be any type"
          }
        }
      },
      "output_metadata": {
        "description": "Cell output metadata.",
        "type": "object",
        "additionalProperties": true
      },
      "multiline_string": {
        "oneOf": [
          { "type": "string" },
          {
            "type": "array",
            "items": { "type": "string" }
          }
        ]
      }
    }
  }
}
nbformat-5.9.1/nbformat/v4/nbjson.py000066400000000000000000000036531445275403000173550ustar00rootroot00000000000000"""Read and write notebooks in JSON format."""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

import copy
import json

from nbformat.notebooknode import from_dict

from .rwbase import NotebookReader, NotebookWriter, rejoin_lines, split_lines, strip_transient


class BytesEncoder(json.JSONEncoder):
    """A JSON encoder that accepts b64 (and other *ascii*) bytestrings."""

    def default(self, obj):
        """Get the default value of an object."""
        if isinstance(obj, bytes):
            return obj.decode("ascii")
        return json.JSONEncoder.default(self, obj)


class JSONReader(NotebookReader):
    """A JSON notebook reader."""

    def reads(self, s, **kwargs):
        """Read a JSON string into a Notebook object"""
        nb = json.loads(s, **kwargs)
        nb = self.to_notebook(nb, **kwargs)
        return nb

    def to_notebook(self, d, **kwargs):
        """Convert a disk-format notebook dict to in-memory NotebookNode

        handles multi-line values as strings, scrubbing of transient values, etc.
        """
        nb = from_dict(d)
        nb = rejoin_lines(nb)
        nb = strip_transient(nb)
        return nb


class JSONWriter(NotebookWriter):
    """A JSON notebook writer."""

    def writes(self, nb, **kwargs):
        """Serialize a NotebookNode object as a JSON string"""
        kwargs["cls"] = BytesEncoder
        kwargs["indent"] = 1
        kwargs["sort_keys"] = True
        kwargs["separators"] = (",", ": ")
        kwargs.setdefault("ensure_ascii", False)
        # don't modify in-memory dict
        nb = copy.deepcopy(nb)
        if kwargs.pop("split_lines", True):
            nb = split_lines(nb)
        nb = strip_transient(nb)
        return json.dumps(nb, **kwargs)


_reader = JSONReader()
_writer = JSONWriter()

reads = _reader.reads
read = _reader.read
to_notebook = _reader.to_notebook
write = _writer.write
writes = _writer.writes
nbformat-5.9.1/nbformat/v4/rwbase.py000066400000000000000000000102421445275403000173370ustar00rootroot00000000000000"""Base classes and utilities for readers and writers."""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.


def _is_json_mime(mime):
    """Is a key a JSON mime-type that should be left alone?"""
    return mime == "application/json" or (
        mime.startswith("application/") and mime.endswith("+json")
    )


def _rejoin_mimebundle(data):
    """Rejoin the multi-line string fields in a mimebundle (in-place)"""
    for key, value in list(data.items()):
        if (
            not _is_json_mime(key)
            and isinstance(value, list)
            and all(isinstance(line, str) for line in value)
        ):
            data[key] = "".join(value)
    return data


def rejoin_lines(nb):
    """rejoin multiline text into strings

    For reversing effects of ``split_lines(nb)``.

    This only rejoins lines that have been split, so if text objects were not split
    they will pass through unchanged.

    Used when reading JSON files that may have been passed through split_lines.
    """
    for cell in nb.cells:
        if "source" in cell and isinstance(cell.source, list):
            cell.source = "".join(cell.source)

        attachments = cell.get("attachments", {})
        for _, attachment in attachments.items():
            _rejoin_mimebundle(attachment)

        if cell.get("cell_type", None) == "code":
            for output in cell.get("outputs", []):
                output_type = output.get("output_type", "")
                if output_type in {"execute_result", "display_data"}:
                    _rejoin_mimebundle(output.get("data", {}))
                elif output_type and isinstance(output.get("text", ""), list):
                    output.text = "".join(output.text)
    return nb


_non_text_split_mimes = {
    "application/javascript",
    "image/svg+xml",
}


def _split_mimebundle(data):
    """Split multi-line string fields in a mimebundle (in-place)"""
    for key, value in list(data.items()):
        if isinstance(value, str) and (key.startswith("text/") or key in _non_text_split_mimes):
            data[key] = value.splitlines(True)
    return data


def split_lines(nb):
    """split likely multiline text into lists of strings

    For file output more friendly to line-based VCS. ``rejoin_lines(nb)`` will
    reverse the effects of ``split_lines(nb)``.

    Used when writing JSON files.
    """
    for cell in nb.cells:
        source = cell.get("source", None)
        if isinstance(source, str):
            cell["source"] = source.splitlines(True)

        attachments = cell.get("attachments", {})
        for _, attachment in attachments.items():
            _split_mimebundle(attachment)

        if cell.cell_type == "code":
            for output in cell.outputs:
                if output.output_type in {"execute_result", "display_data"}:
                    _split_mimebundle(output.get("data", {}))
                elif output.output_type == "stream" and isinstance(output.text, str):
                    output.text = output.text.splitlines(True)
    return nb


def strip_transient(nb):
    """Strip transient values that shouldn't be stored in files.

    This should be called in *both* read and write.
    """
    nb.metadata.pop("orig_nbformat", None)
    nb.metadata.pop("orig_nbformat_minor", None)
    nb.metadata.pop("signature", None)
    for cell in nb.cells:
        cell.metadata.pop("trusted", None)
    return nb


class NotebookReader:
    """A class for reading notebooks."""

    def reads(self, s, **kwargs):
        """Read a notebook from a string."""
        msg = "reads must be implemented in a subclass"
        raise NotImplementedError(msg)

    def read(self, fp, **kwargs):
        """Read a notebook from a file like object"""
        nbs = fp.read()
        return self.reads(nbs, **kwargs)


class NotebookWriter:
    """A class for writing notebooks."""

    def writes(self, nb, **kwargs):
        """Write a notebook to a string."""
        msg = "writes must be implemented in a subclass"
        raise NotImplementedError(msg)

    def write(self, nb, fp, **kwargs):
        """Write a notebook to a file like object"""
        nbs = self.writes(nb, **kwargs)
        return fp.write(nbs)
nbformat-5.9.1/nbformat/validator.py000066400000000000000000000540621445275403000175200ustar00rootroot00000000000000"""Notebook format validators."""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.


import json
import os
import pprint
import warnings
from copy import deepcopy
from textwrap import dedent
from typing import Any, Optional, Tuple

from ._imports import import_item
from .corpus.words import generate_corpus_id
from .json_compat import ValidationError, _validator_for_name, get_current_validator
from .reader import get_version
from .warnings import DuplicateCellId, MissingIDFieldWarning

validators = {}
_deprecated = object()


def _relax_additional_properties(obj):
    """relax any `additionalProperties`"""
    if isinstance(obj, dict):
        for key, value in obj.items():
            value = (  # noqa
                True if key == "additionalProperties" else _relax_additional_properties(value)
            )
            obj[key] = value
    elif isinstance(obj, list):
        for i, value in enumerate(obj):
            obj[i] = _relax_additional_properties(value)
    return obj


def _allow_undefined(schema):
    schema["definitions"]["cell"]["oneOf"].append({"$ref": "#/definitions/unrecognized_cell"})
    schema["definitions"]["output"]["oneOf"].append({"$ref": "#/definitions/unrecognized_output"})
    return schema


def get_validator(version=None, version_minor=None, relax_add_props=False, name=None):
    """Load the JSON schema into a Validator"""
    if version is None:
        from . import current_nbformat

        version = current_nbformat

    v = import_item("nbformat.v%s" % version)
    current_minor = getattr(v, "nbformat_minor", 0)
    if version_minor is None:
        version_minor = current_minor

    current_validator = _validator_for_name(name) if name else get_current_validator()

    version_tuple = (current_validator.name, version, version_minor)

    if version_tuple not in validators:
        try:
            schema_json = _get_schema_json(v, version=version, version_minor=version_minor)
        except AttributeError:
            return None

        if current_minor < version_minor:
            # notebook from the future, relax all `additionalProperties: False` requirements
            schema_json = _relax_additional_properties(schema_json)
            # and allow undefined cell types and outputs
            schema_json = _allow_undefined(schema_json)

        validators[version_tuple] = current_validator(schema_json)

    if relax_add_props:
        try:
            schema_json = _get_schema_json(v, version=version, version_minor=version_minor)
        except AttributeError:
            return None

        # this allows properties to be added for intermediate
        # representations while validating for all other kinds of errors
        schema_json = _relax_additional_properties(schema_json)
        validators[version_tuple] = current_validator(schema_json)

    return validators[version_tuple]


def _get_schema_json(v, version=None, version_minor=None):
    """
    Gets the json schema from a given imported library and nbformat version.
    """
    if (version, version_minor) in v.nbformat_schema:
        schema_path = os.path.join(
            os.path.dirname(v.__file__), v.nbformat_schema[(version, version_minor)]
        )
    elif version_minor > v.nbformat_minor:
        # load the latest schema
        schema_path = os.path.join(os.path.dirname(v.__file__), v.nbformat_schema[(None, None)])
    else:
        msg = "Cannot find appropriate nbformat schema file."
        raise AttributeError(msg)
    with open(schema_path) as f:
        schema_json = json.load(f)
    return schema_json


def isvalid(nbjson, ref=None, version=None, version_minor=None):
    """Checks whether the given notebook JSON conforms to the current
    notebook format schema. Returns True if the JSON is valid, and
    False otherwise.

    To see the individual errors that were encountered, please use the
    `validate` function instead.
    """
    orig = deepcopy(nbjson)
    try:
        with warnings.catch_warnings():
            warnings.filterwarnings("ignore", category=DeprecationWarning)
            warnings.filterwarnings("ignore", category=MissingIDFieldWarning)
            validate(nbjson, ref, version, version_minor, repair_duplicate_cell_ids=False)
    except ValidationError:
        return False
    else:
        return True
    finally:
        if nbjson != orig:
            raise AssertionError


def _format_as_index(indices):
    """
    (from jsonschema._utils.format_as_index, copied to avoid relying on private API)

    Construct a single string containing indexing operations for the indices.

    For example, [1, 2, "foo"] -> [1][2]["foo"]
    """

    if not indices:
        return ""
    return "[%s]" % "][".join(repr(index) for index in indices)


_ITEM_LIMIT = 16
_STR_LIMIT = 64


def _truncate_obj(obj):
    """Truncate objects for use in validation tracebacks

    Cell and output lists are squashed, as are long strings, lists, and dicts.
    """
    if isinstance(obj, dict):
        truncated_dict = {k: _truncate_obj(v) for k, v in list(obj.items())[:_ITEM_LIMIT]}
        if isinstance(truncated_dict.get("cells"), list):
            truncated_dict["cells"] = ["...%i cells..." % len(obj["cells"])]
        if isinstance(truncated_dict.get("outputs"), list):
            truncated_dict["outputs"] = ["...%i outputs..." % len(obj["outputs"])]

        if len(obj) > _ITEM_LIMIT:
            truncated_dict["..."] = "%i keys truncated" % (len(obj) - _ITEM_LIMIT)
        return truncated_dict
    elif isinstance(obj, list):
        truncated_list = [_truncate_obj(item) for item in obj[:_ITEM_LIMIT]]
        if len(obj) > _ITEM_LIMIT:
            truncated_list.append("...%i items truncated..." % (len(obj) - _ITEM_LIMIT))
        return truncated_list
    elif isinstance(obj, str):
        truncated_str = obj[:_STR_LIMIT]
        if len(obj) > _STR_LIMIT:
            truncated_str += "..."
        return truncated_str
    else:
        return obj


class NotebookValidationError(ValidationError):
    """Schema ValidationError with truncated representation

    to avoid massive verbose tracebacks.
    """

    def __init__(self, original, ref=None):
        """Initialize the error class."""
        self.original = original
        self.ref = getattr(self.original, "ref", ref)
        self.message = self.original.message

    def __getattr__(self, key):
        """Get an attribute from the error."""
        return getattr(self.original, key)

    def __unicode__(self):
        """Custom str for validation errors

        avoids dumping full schema and notebook to logs
        """
        error = self.original
        instance = _truncate_obj(error.instance)

        return "\n".join(
            [
                error.message,
                "",
                "Failed validating {!r} in {}{}:".format(
                    error.validator,
                    self.ref or "notebook",
                    _format_as_index(list(error.relative_schema_path)[:-1]),
                ),
                "",
                "On instance%s:" % _format_as_index(error.relative_path),
                pprint.pformat(instance, width=78),
            ]
        )

    __str__ = __unicode__


def better_validation_error(error, version, version_minor):
    """Get better ValidationError on oneOf failures

    oneOf errors aren't informative.
    if it's a cell type or output_type error,
    try validating directly based on the type for a better error message
    """
    if not len(error.schema_path):
        return error
    key = error.schema_path[-1]
    ref = None
    if key.endswith("Of"):
        if isinstance(error.instance, dict):
            if "cell_type" in error.instance:
                ref = error.instance["cell_type"] + "_cell"
            elif "output_type" in error.instance:
                ref = error.instance["output_type"]

        if ref:
            try:
                validate(
                    error.instance,
                    ref,
                    version=version,
                    version_minor=version_minor,
                )
            except ValidationError as sub_error:
                # keep extending relative path
                error.relative_path.extend(sub_error.relative_path)
                sub_error.relative_path = error.relative_path
                better = better_validation_error(sub_error, version, version_minor)
                if better.ref is None:
                    better.ref = ref
                return better
            except Exception:  # noqa
                # if it fails for some reason,
                # let the original error through
                pass
    return NotebookValidationError(error, ref)


def normalize(
    nbdict: Any,
    version: Optional[int] = None,
    version_minor: Optional[int] = None,
    *,
    relax_add_props: bool = False,
    strip_invalid_metadata: bool = False,
) -> Tuple[int, Any]:
    """
    Normalise a notebook prior to validation.

    This tries to implement a couple of normalisation steps to standardise
    notebooks and make validation easier.

    You should in general not rely on this function and make sure the notebooks
    that reach nbformat are already in a normal form. If not you likely have a bug,
    and may have security issues.

    Parameters
    ----------
    nbdict : dict
        notebook document
    version : int
    version_minor : int
    relax_add_props : bool
        Whether to allow extra property in the Json schema validating the
        notebook.
    strip_invalid_metadata : bool
        Whether to strip metadata that does not exist in the Json schema when
        validating the notebook.

    Returns
    -------
    changes : int
        number of changes in the notebooks
    notebook : dict
        deep-copy of the original object with relevant changes.

    """
    nbdict = deepcopy(nbdict)
    nbdict_version, nbdict_version_minor = get_version(nbdict)
    if version is None:
        version = nbdict_version
    if version_minor is None:
        version_minor = nbdict_version_minor
    return _normalize(
        nbdict,
        version,
        version_minor,
        True,
        relax_add_props=relax_add_props,
        strip_invalid_metadata=strip_invalid_metadata,
    )


def _normalize(
    nbdict: Any,
    version: int,
    version_minor: int,
    repair_duplicate_cell_ids: bool,
    relax_add_props: bool,
    strip_invalid_metadata: bool,
) -> Tuple[int, Any]:
    """
    Private normalisation routine.

    This function attempts to normalize the `nbdict` passed to it.

    As `_normalize()` is currently used both in `validate()` (for
    historical reasons), and in the `normalize()` public function,
    `_normalize()` does currently mutate `nbdict`.
    Ideally, once `validate()` stops calling `_normalize()`, `_normalize()`
    may stop mutating `nbdict`.

    """
    changes = 0

    if (version, version_minor) >= (4, 5):
        # if we support cell ids ensure default ids are provided
        for cell in nbdict["cells"]:
            if "id" not in cell:
                warnings.warn(
                    "Code cell is missing an id field, this will become"
                    " a hard error in future nbformat versions. You may want"
                    " to use `normalize()` on your notebooks before validations"
                    " (available since nbformat 5.1.4). Previous versions of nbformat"
                    " are fixing this issue transparently, and will stop doing so"
                    " in the future.",
                    MissingIDFieldWarning,
                    stacklevel=3,
                )
                # Generate cell ids if any are missing
                if repair_duplicate_cell_ids:
                    cell["id"] = generate_corpus_id()
                    changes += 1

        # if we support cell ids check for uniqueness when validating the whole notebook
        seen_ids = set()
        for cell in nbdict["cells"]:
            if "id" not in cell:
                continue
            cell_id = cell["id"]
            if cell_id in seen_ids:
                # Best effort to repair if we find a duplicate id
                if repair_duplicate_cell_ids:
                    new_id = generate_corpus_id()
                    cell["id"] = new_id
                    changes += 1
                    warnings.warn(
                        f"Non-unique cell id {cell_id!r} detected. Corrected to {new_id!r}.",
                        DuplicateCellId,
                        stacklevel=3,
                    )
                else:
                    msg = f"Non-unique cell id '{cell_id}' detected."
                    raise ValidationError(msg)
            seen_ids.add(cell_id)
    if strip_invalid_metadata:
        changes += _strip_invalida_metadata(
            nbdict, version, version_minor, relax_add_props=relax_add_props
        )
    return changes, nbdict


def _dep_warn(field):
    warnings.warn(
        dedent(
            f"""`{field}` kwargs of validate has been deprecated for security
        reasons, and will be removed soon.

        Please explicitly use the `n_changes, new_notebook = nbformat.validator.normalize(old_notebook, ...)` if you wish to
        normalise your notebook. `normalize` is available since nbformat 5.5.0

        """
        ),
        DeprecationWarning,
        stacklevel=3,
    )


def validate(  # noqa
    nbdict: Any = None,
    ref: Optional[str] = None,
    version: Optional[int] = None,
    version_minor: Optional[int] = None,
    relax_add_props: bool = False,
    nbjson: Any = None,
    repair_duplicate_cell_ids: bool = _deprecated,  # type: ignore
    strip_invalid_metadata: bool = _deprecated,  # type: ignore
) -> None:
    """Checks whether the given notebook dict-like object
    conforms to the relevant notebook format schema.

    Parameters
    ----------
    nbdict : dict
        notebook document
    ref : optional, str
        reference to the subset of the schema we want to validate against.
        for example ``"markdown_cell"``, `"code_cell"` ....
    version : int
    version_minor : int
    relax_add_props : bool
        Wether to allow extra properties in the JSON schema validating the notebook.
        When True, all known fields are validated, but unknown fields are ignored.
    nbjson
    repair_duplicate_cell_ids : bool
        Deprecated since 5.5.0 - will be removed in the future.
    strip_invalid_metadata : bool
        Deprecated since 5.5.0 - will be removed in the future.

    Returns
    -------
    None

    Raises
    ------
    ValidationError if not valid.

    Notes
    -----
    Prior to Nbformat 5.5.0 the `validate` and `isvalid` method would silently
    try to fix invalid notebook and mutate arguments. This behavior is deprecated
    and will be removed in a near future.

    Please explicitly call `normalize` if you need to normalize notebooks.
    """
    assert isinstance(ref, str) or ref is None  # noqa

    if strip_invalid_metadata is _deprecated:
        strip_invalid_metadata = False
    else:
        _dep_warn("strip_invalid_metadata")
        pass

    if repair_duplicate_cell_ids is _deprecated:
        repair_duplicate_cell_ids = True
    else:
        _dep_warn("repair_duplicate_cell_ids")
        pass

    # backwards compatibility for nbjson argument
    if nbdict is not None:
        pass
    elif nbjson is not None:
        nbdict = nbjson
    else:
        msg = "validate() missing 1 required argument: 'nbdict'"
        raise TypeError(msg)

    if ref is None:
        # if ref is not specified, we have a whole notebook, so we can get the version
        nbdict_version, nbdict_version_minor = get_version(nbdict)
        if version is None:
            version = nbdict_version
        if version_minor is None:
            version_minor = nbdict_version_minor
    else:
        # if ref is specified, and we don't have a version number, assume we're validating against 1.0
        if version is None:  # noqa
            version, version_minor = 1, 0

    if ref is None:
        assert isinstance(version, int)  # noqa
        assert isinstance(version_minor, int)  # noqa
        _normalize(
            nbdict,
            version,
            version_minor,
            repair_duplicate_cell_ids,
            relax_add_props=relax_add_props,
            strip_invalid_metadata=strip_invalid_metadata,
        )

    for error in iter_validate(
        nbdict,
        ref=ref,
        version=version,
        version_minor=version_minor,
        relax_add_props=relax_add_props,
        strip_invalid_metadata=strip_invalid_metadata,
    ):
        raise error


def _get_errors(
    nbdict: Any, version: int, version_minor: int, relax_add_props: bool, *args: Any
) -> Any:
    validator = get_validator(version, version_minor, relax_add_props=relax_add_props)
    if not validator:
        msg = f"No schema for validating v{version}.{version_minor} notebooks"
        raise ValidationError(msg)
    iter_errors = validator.iter_errors(nbdict, *args)
    errors = list(iter_errors)
    # jsonschema gives the best error messages.
    if len(errors) and validator.name != "jsonschema":
        validator = get_validator(
            version=version,
            version_minor=version_minor,
            relax_add_props=relax_add_props,
            name="jsonschema",
        )
        return validator.iter_errors(nbdict, *args)
    return iter(errors)


def _strip_invalida_metadata(  # noqa
    nbdict: Any, version: int, version_minor: int, relax_add_props: bool
) -> int:
    """
    This function tries to extract metadata errors from the validator and fix
    them if necessary. This mostly mean stripping unknown keys from metadata
    fields, or removing metadata fields altogether.

    Parameters
    ----------
    nbdict : dict
        notebook document
    version : int
    version_minor : int
    relax_add_props : bool
        Wether to allow extra property in the Json schema validating the
        notebook.

    Returns
    -------
    int
        number of modifications

    """
    errors = _get_errors(nbdict, version, version_minor, relax_add_props)
    changes = 0
    if len(list(errors)) > 0:
        # jsonschema gives a better error tree.
        validator = get_validator(
            version=version,
            version_minor=version_minor,
            relax_add_props=relax_add_props,
            name="jsonschema",
        )
        if not validator:
            msg = f"No jsonschema for validating v{version}.{version_minor} notebooks"
            raise ValidationError(msg)
        errors = validator.iter_errors(nbdict)
        error_tree = validator.error_tree(errors)
        if "metadata" in error_tree:
            for key in error_tree["metadata"]:
                nbdict["metadata"].pop(key, None)
                changes += 1

        if "cells" in error_tree:
            number_of_cells = len(nbdict.get("cells", 0))
            for cell_idx in range(number_of_cells):
                # Cells don't report individual metadata keys as having failed validation
                # Instead it reports that it failed to validate against each cell-type definition.
                # We have to delve into why those definitions failed to uncover which metadata
                # keys are misbehaving.
                if "oneOf" in error_tree["cells"][cell_idx].errors:
                    intended_cell_type = nbdict["cells"][cell_idx]["cell_type"]
                    schemas_by_index = [
                        ref["$ref"]
                        for ref in error_tree["cells"][cell_idx].errors["oneOf"].schema["oneOf"]
                    ]
                    cell_type_definition_name = f"#/definitions/{intended_cell_type}_cell"
                    if cell_type_definition_name in schemas_by_index:
                        schema_index = schemas_by_index.index(cell_type_definition_name)
                        for error in error_tree["cells"][cell_idx].errors["oneOf"].context:
                            rel_path = error.relative_path
                            error_for_intended_schema = error.schema_path[0] == schema_index
                            is_top_level_metadata_key = (
                                len(rel_path) == 2 and rel_path[0] == "metadata"  # noqa
                            )
                            if error_for_intended_schema and is_top_level_metadata_key:
                                nbdict["cells"][cell_idx]["metadata"].pop(rel_path[1], None)
                                changes += 1

    return changes


def iter_validate(
    nbdict=None,
    ref=None,
    version=None,
    version_minor=None,
    relax_add_props=False,
    nbjson=None,
    strip_invalid_metadata=False,
):
    """Checks whether the given notebook dict-like object conforms to the
    relevant notebook format schema.

    Returns a generator of all ValidationErrors if not valid.

    Notes
    -----
    To fix: For security reasons, this function should *never* mutate its `nbdict` argument, and
    should *never* try to validate a mutated or modified version of its notebook.

    """
    # backwards compatibility for nbjson argument
    if nbdict is not None:
        pass
    elif nbjson is not None:
        nbdict = nbjson
    else:
        msg = "iter_validate() missing 1 required argument: 'nbdict'"
        raise TypeError(msg)

    if version is None:
        version, version_minor = get_version(nbdict)

    if ref:
        try:
            errors = _get_errors(
                nbdict,
                version,
                version_minor,
                relax_add_props,
                {"$ref": "#/definitions/%s" % ref},
            )
        except ValidationError as e:
            yield e
            return

    else:
        if strip_invalid_metadata:
            _strip_invalida_metadata(nbdict, version, version_minor, relax_add_props)

        # Validate one more time to ensure that us removing metadata
        # didn't cause another complex validation issue in the schema.
        # Also to ensure that higher-level errors produced by individual metadata validation
        # failures are removed.
        try:
            errors = _get_errors(nbdict, version, version_minor, relax_add_props)
        except ValidationError as e:
            yield e
            return

    for error in errors:
        yield better_validation_error(error, version, version_minor)
nbformat-5.9.1/nbformat/warnings.py000066400000000000000000000013251445275403000173550ustar00rootroot00000000000000"""
Warnings that can be emitted by nbformat.
"""


class MissingIDFieldWarning(FutureWarning):
    """

    This warning is emitted in the validation step of nbformat as we used to
    mutate the structure which is cause signature issues.

    This will be turned into an error at later point.

    We subclass FutureWarning as we will change the behavior in the future.

    """

    pass


class DuplicateCellId(FutureWarning):
    """

    This warning is emitted in the validation step of nbformat as we used to
    mutate the structure which is cause signature issues.

    This will be turned into an error at later point.

    We subclass FutureWarning as we will change the behavior in the future.
    """

    pass
nbformat-5.9.1/package.json000066400000000000000000000012341445275403000156300ustar00rootroot00000000000000{
    "name": "nbformat-schema",
    "version": "5.9.1",
    "description": "JSON schemata for Jupyter notebook formats",
    "main": "index.js",
    "files": [
        "nbformat/v3/nbformat.v3.schema.json",
        "nbformat/v4/nbformat.v4.schema.json"
    ],
    "repository": {
        "type": "git",
        "url": "git+https://github.com/jupyter/nbformat.git"
    },
    "keywords": [
        "jupyter",
        "notebook",
        "json-schema"
    ],
    "author": "Project Jupyter Contributors",
    "license": "BSD-3-Clause",
    "bugs": {
        "url": "https://github.com/jupyter/nbformat/issues"
    },
    "homepage": "https://nbformat.readthedocs.io"
}
nbformat-5.9.1/pyproject.toml000066400000000000000000000126531445275403000162650ustar00rootroot00000000000000[build-system]
requires = ["hatchling>=1.5", "hatch-nodejs-version"]
build-backend = "hatchling.build"

[project]
name = "nbformat"
dynamic = ["version"]
description = "The Jupyter Notebook format"
license = { file = "LICENSE" }
keywords = ["Interactive", "Interpreter", "Shell", "Web"]
classifiers = [
    "Intended Audience :: Developers",
    "Intended Audience :: System Administrators",
    "Intended Audience :: Science/Research",
    "License :: OSI Approved :: BSD License",
    "Programming Language :: Python",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.8",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11"
]
requires-python = ">=3.8"
dependencies = [
    "fastjsonschema",
    "jsonschema>=2.6",
    "jupyter_core",
    "traitlets>=5.1"
]

[[project.authors]]
name = "Jupyter Development Team"
email = "jupyter@googlegroups.com"

[project.readme]
text = "This package contains the base implementation of the Jupyter Notebook format,\nand Python APIs for working with notebooks."
content-type = "text/plain"

[project.urls]
Homepage = "https://jupyter.org"

[project.optional-dependencies]
docs = [
"myst_parser",
"pydata_sphinx_theme",
"sphinx",
"sphinxcontrib_github_alt",
"sphinxcontrib-spelling",
]
test = [
    "testpath",
    "pytest",
    "pre-commit",
    "pep440"
]

[project.scripts]
jupyter-trust = "nbformat.sign:TrustNotebookApp.launch_instance"

[tool.hatch.version]
source = "nodejs"

[tool.hatch.envs.docs]
features = ["docs"]
[tool.hatch.envs.docs.scripts]
build = "make -C docs html SPHINXOPTS='-W'"

[tool.hatch.envs.test]
features = ["test"]
[tool.hatch.envs.test.scripts]
test = "python -m pytest -vv {args}"
nowarn = "test -W default {args}"

[tool.hatch.envs.cov]
features = ["test"]
dependencies = ["coverage", "pytest-cov"]
[tool.hatch.envs.cov.scripts]
test = "python -m pytest -vv --cov nbformat --cov-branch --cov-report term-missing:skip-covered {args}"
nowarn = "test -W default {args}"

[tool.hatch.envs.typing]
features = ["test"]
dependencies = ["mypy>=0.990"]
[tool.hatch.envs.typing.scripts]
test = "mypy --install-types --non-interactive {args:nbformat tests}"

[tool.hatch.envs.lint]
dependencies = ["black[jupyter]==23.3.0", "mdformat>0.7", "ruff==0.0.276"]
detached = true
[tool.hatch.envs.lint.scripts]
style = [
  "ruff {args:.}",
  "black --check --diff {args:.}",
  "mdformat --check {args:*.md}"
]
fmt = [
  "black {args:.}",
  "ruff --fix {args:.}",
  "mdformat {args:*.md}"
]

[tool.pytest.ini_options]
addopts = "-raXs --durations 10 --color=yes --doctest-modules"
testpaths = [
    "tests/",
]
filterwarnings = [
    "error",
    "ignore:Using or importing the ABCs from 'collections':DeprecationWarning:jsonschema",
    "module:Jupyter is migrating its paths to use standard platformdirs:DeprecationWarning",
    # ignore pytest warnings.
    "ignore:::_pytest",
]

[tool.coverage.report]
exclude_lines = [
  "pragma: no cover",
  "def __repr__",
  "if self.debug:",
  "if settings.DEBUG",
  "raise AssertionError",
  "raise NotImplementedError",
  "if 0:",
  "if __name__ == .__main__.:",
  "class .*\bProtocol\\):",
"@(abc\\.)?abstractmethod",
]

[tool.mypy]
check_untyped_defs = true
disallow_incomplete_defs = true
disallow_untyped_decorators = true
no_implicit_optional = true
pretty = true
show_error_context = true
show_error_codes = true
strict_equality = true
warn_unused_configs = true
warn_unused_ignores = true
warn_redundant_casts = true

[[tool.mypy.overrides]]
module = [
    "fastjsonschema",
    "jsonschema",
    "pysqlite2",
    "testpath"
]
ignore_missing_imports = true

[tool.black]
line-length = 100
skip-string-normalization = true
target-version = ["py37"]
extend-exclude = "^/tests.*ipynb$"

[tool.ruff]
target-version = "py37"
line-length = 100
select = [
  "A", "B", "C", "DTZ", "E", "EM", "F", "FBT", "I", "ICN", "ISC", "N",
  "PLC", "PLE", "PLR", "PLW", "Q", "RUF", "S", "SIM", "T", "TID", "UP",
  "W", "YTT",
]
ignore = [
  # Q000 Single quotes found but double quotes preferred
  "Q000",
  # FBT001 Boolean positional arg in function definition
  "FBT001", "FBT002", "FBT003",
  # E501 Line too long (158 > 100 characters)
  "E501",
  # SIM105 Use `contextlib.suppress(...)`
  "SIM105",
  # PLR0913 Too many arguments to function call
  "PLR0913",
]
unfixable = [
  # Don't touch print statements
  "T201",
  # Don't touch noqa lines
  "RUF100",
]

[tool.ruff.per-file-ignores]
# B011 Do not call assert False since python -O removes these calls
# F841 local variable 'foo' is assigned to but never used
# C408 Unnecessary `dict` call
# E402 Module level import not at top of file
# T201 `print` found
# B007 Loop control variable `i` not used within the loop body.
# N802 Function name `assertIn` should be lowercase
# RUF001 contains ambiguous unicode character '–' (did you mean '-'?)
# S101 Use of `assert` detected
# PLR2004 Magic value used in comparison
# PLC1901 `cell.source == ""` can be simplified
"tests/*" = ["B011", "F841", "C408", "E402", "T201", "B007", "N802", "RUF001", "RUF002", "S101", "PLR2004",
             "PLC1901"]
# F401 `nbxml.to_notebook` imported but unused
"nbformat/*__init__.py" = ["F401"]

[tool.coverage.run]
relative_files = true
source = ["nbformat"]

[tool.interrogate]
ignore-init-module=true
ignore-private=true
ignore-semiprivate=true
ignore-property-decorators=true
ignore-nested-functions=true
ignore-nested-classes=true
fail-under=100

[tool.check-wheel-contents]
ignore = ["W002"]
nbformat-5.9.1/scripts/000077500000000000000000000000001445275403000150315ustar00rootroot00000000000000nbformat-5.9.1/scripts/jupyter-trust000077500000000000000000000002431445275403000176370ustar00rootroot00000000000000#!/usr/bin/env python


def main():
    from nbformat.sign import TrustNotebookApp

    TrustNotebookApp.launch_instance()


if __name__ == "__main__":
    main()
nbformat-5.9.1/tests/000077500000000000000000000000001445275403000145045ustar00rootroot00000000000000nbformat-5.9.1/tests/__init__.py000066400000000000000000000000001445275403000166030ustar00rootroot00000000000000nbformat-5.9.1/tests/base.py000066400000000000000000000007541445275403000157760ustar00rootroot00000000000000"""
Contains base test class for nbformat
"""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

import os
import unittest


class TestsBase(unittest.TestCase):
    """Base tests class."""

    @classmethod
    def fopen(cls, f, mode="r", encoding="utf-8"):
        return open(os.path.join(cls._get_files_path(), f), mode, encoding=encoding)  # noqa

    @classmethod
    def _get_files_path(cls):
        return os.path.dirname(__file__)
nbformat-5.9.1/tests/invalid.ipynb000066400000000000000000000417251445275403000172060ustar00rootroot00000000000000{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus bibendum felis dictum sodales. Ut suscipit, orci ut interdum imperdiet, purus ligula mollis *justo*, non malesuada nisl augue eget lorem. Donec bibendum, erat sit amet porttitor aliquam, urna lorem ornare libero, in vehicula diam diam ut ante. Nam non urna rhoncus, accumsan elit sit amet, mollis tellus. Vestibulum nec tellus metus. Vestibulum tempor, ligula et vehicula rhoncus, sapien turpis faucibus lorem, id dapibus turpis mauris ac orci. Sed volutpat vestibulum venenatis."
   ]
  },
  {
   "cell_type": "heading",
   "level": 2,
   "metadata": {},
   "source": [
    "Printed Using Python"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "bad stream",
     "text": [
      "hello\n"
     ]
    }
   ],
   "source": [
    "print(\"hello\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Pyout"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "\n",
       "HTML\n"
      ],
      "text/plain": [
       ""
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import HTML\n",
    "\n",
    "HTML(\n",
    "    \"\"\"\n",
    "\n",
    "HTML\n",
    "\"\"\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "console.log(\"hi\");"
      ],
      "text/plain": [
       ""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%javascript\n",
    "console.log(\"hi\");"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": [
       "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\n"
      ],
      "text/plain": [
       ""
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import Image\n",
    "\n",
    "Image(\"http://ipython.org/_static/IPy_header.png\")"
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 0
}
nbformat-5.9.1/tests/invalid_cell_id.ipynb000066400000000000000000000013761445275403000206570ustar00rootroot00000000000000{
 "cells": [
  {
   "id": "$illegal_chars",
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'bar'"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"bar\""
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
nbformat-5.9.1/tests/invalid_unique_cell_id.ipynb000066400000000000000000000013421445275403000222360ustar00rootroot00000000000000{
 "cells": [
  {
   "id": "dup",
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"foo\""
   ]
  },
  {
   "id": "dup",
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"foo2\""
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
nbformat-5.9.1/tests/many_tracebacks.ipynb000066400000000000000000000024601445275403000206770ustar00rootroot00000000000000{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'iAmNotDefined' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0miAmNotDefined\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m: name 'iAmNotDefined' is not defined"
     ]
    }
   ],
   "source": [
    "# Imagine this cell called a function which runs things on a cluster and you have an error"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
nbformat-5.9.1/tests/no_min_version.ipynb000066400000000000000000000003741445275403000205770ustar00rootroot00000000000000{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "plaintext"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4
}
nbformat-5.9.1/tests/test2.ipynb000066400000000000000000001320621445275403000166140ustar00rootroot00000000000000{
 "metadata": {
  "name": "01_notebook_introduction"
 },
 "nbformat": 2,
 "worksheets": [
  {
   "cells": [
    {
     "cell_type": "markdown",
     "source": [
      "# An introduction to the Jupyter notebook",
      "",
      "The IPython web notebook is a frontend that allows for new modes",
      "of interaction with IPython: this web-based interface allows you to execute Python and IPython",
      "commands in each input cell just like you would at the IPython terminal or Qt console, but you can",
      "also save an entire session as a document in a file with the `.ipynb` extension.",
      "",
      "The document you are reading now is precisely an example of one such notebook, and we will show you",
      "here how to best use this new interface.",
      "",
      "The first thing to understand is that a notebook consists of a sequence of 'cells' that can contain ",
      "either text (such as this one) or code meant for execution (such as the next one):",
      "",
      "* Text cells can be written using [Markdown syntax](http://daringfireball.net/projects/markdown/syntax) ",
      "(in a future release we will also provide support for reStructuredText and Sphinx integration, and we ",
      "welcome help from interested contributors to make that happen).",
      "",
      "* Code cells take IPython input (i.e. Python code, `%magics`, `!system calls`, etc) like IPython at",
      "the terminal or at the Qt Console.  The only difference is that in order to execute a cell, you *must*",
      "use `Shift-Enter`, as pressing `Enter` will add a new line of text to the cell.  When you type ",
      "`Shift-Enter`, the cell content is executed, output displayed and a new cell is created below.  Try",
      "it now by putting your cursor on the next cell and typing `Shift-Enter`:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "\"This is the new Jupyter notebook\""
     ],
     "language": "python",
     "outputs": [
      {
       "output_type": "pyout",
       "prompt_number": 1,
       "text": [
        "'This is the new Jupyter notebook'"
       ]
      }
     ],
     "prompt_number": 1
    },
    {
     "cell_type": "markdown",
     "source": [
      "You can re-execute the same cell over and over as many times as you want.  Simply put your",
      "cursor in the cell again, edit at will, and type `Shift-Enter` to execute.  ",
      "",
      "**Tip:** A cell can also be executed",
      "*in-place*, where IPython executes its content but leaves the cursor in the same cell.  This is done by",
      "typing `Ctrl-Enter` instead, and is useful if you want to quickly run a command to check something ",
      "before tping the real content you want to leave in the cell. For example, in the next cell, try issuing",
      "several system commands in-place with `Ctrl-Enter`, such as `pwd` and then `ls`:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "ls"
     ],
     "language": "python",
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "00_notebook_tour.ipynb          formatting.ipynb  sympy_quantum_computing.ipynb",
        "01_notebook_introduction.ipynb  python-logo.svg   trapezoid_rule.ipynb",
        "display_protocol.ipynb          sympy.ipynb"
       ]
      }
     ],
     "prompt_number": 2
    },
    {
     "cell_type": "markdown",
     "source": [
      "In a cell, you can type anything from a single python expression to an arbitrarily long amount of code ",
      "(although for reasons of readability, you should probably limit this to a few dozen lines):"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "def f(x):",
      "    \"\"\"My function",
      "    x : parameter\"\"\"",
      "    ",
      "    return x+1",
      "",
      "print \"f(3) = \", f(3)"
     ],
     "language": "python",
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "f(3) =  4"
       ]
      }
     ],
     "prompt_number": 3
    },
    {
     "cell_type": "markdown",
     "source": [
      "## User interface",
      "",
      "When you start a new notebook server with `ipython notebook`, your",
      "browser should open into the *Dashboard*, a page listing all notebooks",
      "available in the current directory as well as letting you create new",
      "notebooks.  In this page, you can also drag and drop existing `.py` files",
      "over the file list to import them as notebooks (see the manual for ",
      "[further details on how these files are ",
      "interpreted](http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html)).",
      "",
      "Once you open an existing notebook (like this one) or create a new one,",
      "you are in the main notebook interface, which consists of a main editing",
      "area (where these cells are contained) as well as a collapsible left panel, ",
      "a permanent header area at the top, and a pager that rises from the",
      "bottom when needed and can be collapsed again."
     ]
    },
    {
     "cell_type": "markdown",
     "source": [
      "### Main editing area",
      "",
      "Here, you can move with the arrow keys or using the ",
      "scroll bars.  The cursor enters code cells immediately, but only selects",
      "text (markdown) cells without entering in them; to enter a text cell,",
      "use `Enter`, and `Shift-Enter` to exit it again (just like to execute a ",
      "code cell)."
     ]
    },
    {
     "cell_type": "markdown",
     "source": [
      "### Left panel",
      "",
      "This panel contains a number of panes that can be",
      "collapsed vertically by clicking on their title bar, and the whole panel",
      "can also be collapsed by clicking on the vertical divider (note that you",
      "can not *drag* the divider, for now you can only click on it).",
      "",
      "The *Notebook* section contains actions that pertain to the whole notebook,",
      "such as downloading the current notebook either in its original format",
      "or as a `.py` script, and printing it.  When you click the `Print` button,",
      "a new HTML page opens with a static copy of the notebook; you can then",
      "use your web browser's mechanisms to save or print this file.",
      "",
      "The *Cell* section lets you manipulate individual cells, and the names should ",
      "be fairly self-explanatory.",
      "",
      "The *Kernel* section lets you signal the kernel executing your code. ",
      "`Interrupt` does the equivalent of hitting `Ctrl-C` at a terminal, and",
      "`Restart` fully kills the kernel process and starts a fresh one.  Obviously",
      "this means that all your previous variables are destroyed, but it also",
      "makes it easy to get a fresh kernel in which to re-execute a notebook, perhaps",
      "after changing an extension module for which Python's `reload` mechanism",
      "does not work.   If you check the 'Kill kernel upon exit' box, when you ",
      "close the page IPython will automatically shut down the running kernel;",
      "otherwise the kernels won't close until you stop the whole ",
      "",
      "The *Help* section contains links to the documentation of some projects",
      "closely related to IPython as well as the minimal keybindings you need to",
      "know.  But you should use `Ctrl-m h` (or click the `QuickHelp` button at",
      "the top) and learn some of the other keybindings, as it will make your ",
      "workflow much more fluid and efficient.",
      "",
      "The *Configuration* section at the bottom lets you change some values",
      "related to the display of tooltips and the behavior of the tab completer."
     ]
    },
    {
     "cell_type": "markdown",
     "source": [
      "### Header bar",
      "",
      "The header area at the top allows you to rename an existing ",
      "notebook and open up a short help tooltip.  This area also indicates",
      "with a red **Busy** mark on the right whenever the kernel is busy executing",
      "code."
     ]
    },
    {
     "cell_type": "markdown",
     "source": [
      "### The pager at the bottom",
      "",
      "Whenever IPython needs to display additional ",
      "information, such as when you type `somefunction?` in a cell, the notebook",
      "opens a pane at the bottom where this information is shown.  You can keep",
      "this pager pane open for reference (it doesn't block input in the main area)",
      "or dismiss it by clicking on its divider bar."
     ]
    },
    {
     "cell_type": "markdown",
     "source": [
      "### Tab completion and tooltips",
      "",
      "The notebook uses the same underlying machinery for tab completion that ",
      "IPython uses at the terminal, but displays the information differently.",
      "Whey you complete with the `Tab` key, IPython shows a drop list with all",
      "available completions.  If you type more characters while this list is open,",
      "IPython automatically eliminates from the list options that don't match the",
      "new characters; once there is only one option left you can hit `Tab` once",
      "more (or `Enter`) to complete.  You can also select the completion you",
      "want with the arrow keys or the mouse, and then hit `Enter`.",
      "",
      "In addition, if you hit `Tab` inside of open parentheses, IPython will ",
      "search for the docstring of the last object left of the parens and will",
      "display it on a tooltip. For example, type `list(` and you will",
      "see the docstring for the builtin `list` constructor:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": true,
     "input": [
      "# Position your cursor after the ( and hit the Tab key:",
      "list("
     ],
     "language": "python",
     "outputs": []
    },
    {
     "cell_type": "markdown",
     "source": [
      "## The frontend/kernel model",
      "",
      "The Jupyter notebook works on a client/server model where an *IPython kernel*",
      "starts in a separate process and acts as a server to executes the code you type,",
      "while the web browser provides acts as a client, providing a front end environment",
      "for you to type.  But one kernel is capable of simultaneously talking to more than",
      "one client, and they do not all need to be of the same kind.  All IPython frontends",
      "are capable of communicating with a kernel, and any number of them can be active",
      "at the same time.  In addition to allowing you to have, for example, more than one",
      "browser session active, this lets you connect clients with different user interface features.",
      "",
      "For example, you may want to connect a Qt console to your kernel and use it as a help",
      "browser, calling `??` on objects in the Qt console (whose pager is more flexible than the",
      "one in the notebook).  You can start a new Qt console connected to your current kernel by ",
      "using the `%qtconsole` magic, this will automatically detect the necessary connection",
      "information.",
      "",
      "If you want to open one manually, or want to open a text console from a terminal, you can ",
      "get your kernel's connection information with the `%connect_info` magic:"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%connect_info"
     ],
     "language": "python",
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "{",
        "  \"stdin_port\": 53970, ",
        "  \"ip\": \"127.0.0.1\", ",
        "  \"hb_port\": 53971, ",
        "  \"key\": \"30daac61-6b73-4bae-a7d9-9dca538794d5\", ",
        "  \"shell_port\": 53968, ",
        "  \"iopub_port\": 53969",
        "}",
        "",
        "Paste the above JSON into a file, and connect with:",
        "    $> ipython  --existing ",
        "or, if you are local, you can connect with just:",
        "    $> ipython  --existing kernel-dd85d1cc-c335-44f4-bed8-f1a2173a819a.json ",
        "or even just:",
        "    $> ipython  --existing ",
        "if this is the most recent IPython session you have started."
       ]
      }
     ],
     "prompt_number": 4
    },
    {
     "cell_type": "markdown",
     "source": [
      "## The kernel's `raw_input` and `%debug`",
      "",
      "The one feature the notebook currently doesn't support as a client is the ability to send data to the kernel's",
      "standard input socket.  That is, if the kernel requires information to be typed interactively by calling the",
      "builtin `raw_input` function, the notebook will be blocked.  This happens for example if you run a script",
      "that queries interactively for parameters, and very importantly, is how the interactive IPython debugger that ",
      "activates when you type `%debug` works.",
      "",
      "So, in order to be able to use `%debug` or anything else that requires `raw_input`, you can either use a Qt ",
      "console or a terminal console:",
      "",
      "- From the notebook, typing `%qtconsole` finds all the necessary connection data for you.",
      "- From the terminal, first type `%connect_info` while still in the notebook, and then copy and paste the ",
      "resulting information, using `qtconsole` or `console` depending on which type of client you want."
     ]
    },
    {
     "cell_type": "markdown",
     "source": [
      "## Display of complex objects",
      "",
      "As the 'tour' notebook shows, the Jupyter notebook has fairly sophisticated display capabilities.  In addition",
      "to the examples there, you can study the `display_protocol` notebook in this same examples folder, to ",
      "learn how to customize arbitrary objects (in your own code or external libraries) to display in the notebook",
      "in any way you want, including graphical forms or mathematical expressions."
     ]
    },
    {
     "cell_type": "markdown",
     "source": [
      "## Plotting support",
      "",
      "As we've explained already, the notebook is just another frontend talking to the same IPython kernel that",
      "you're already familiar with, so the same options for plotting support apply.",
      "",
      "If you start the notebook with `--pylab`, you will get matplotlib's floating, interactive windows and you",
      "can call the `display` function to paste figures into the notebook document.  If you start it with ",
      "`--pylab inline`, all plots will appear inline automatically.  In this regard, the notebook works identically",
      "to the Qt console.",
      "",
      "Note that if you start the notebook server with pylab support, *all* kernels are automatically started in",
      "pylab mode and with the same choice of backend (i.e. floating windows or inline figures).  But you can also",
      "start the notebook server simply by typing `ipython notebook`, and then selectively turn on pylab support ",
      "only for the notebooks you want by using the `%pylab` magic (see its docstring for details)."
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%pylab inline",
      "plot(rand(100))"
     ],
     "language": "python",
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "",
        "Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline].",
        "For more information, type 'help(pylab)'."
       ]
      },
      {
       "output_type": "pyout",
       "prompt_number": 5,
       "text": [
        "[]"
       ]
      },
      {
       "output_type": "display_data",
       "png": "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\n"
      }
     ],
     "prompt_number": 5
    },
    {
     "cell_type": "markdown",
     "source": [
      "## Security",
      "",
      "By default the notebook only listens on localhost, so it does not expose your computer to attacks coming from",
      "the internet.  By default the notebook does not require any authentication, but you can configure it to",
      "ask for a password before allowing access to the files.  ",
      "",
      "Furthermore, you can require the notebook to encrypt all communications by using SSL and making all connections",
      "using the https protocol instead of plain http.  This is a good idea if you decide to run your notebook on",
      "addresses that are visible from the internet.  For further details on how to configure this, see the",
      "[security section](http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html#security) of the ",
      "manual.",
      "",
      "Finally, note that you can also run a notebook with the `--read-only` flag, which lets you provide access",
      "to your notebook documents to others without letting them execute code (which can be useful to broadcast",
      "a computation to colleagues or students, for example).  The read-only flag behaves differently depending",
      "on whether the server has a password or not:",
      "",
      "- Passwordless server: users directly see all notebooks in read-only mode.",
      "- Password-protected server: users can see all notebooks in read-only mode, but a login button is available",
      "and once a user authenticates, he or she obtains write/execute privileges.",
      "",
      "The first case above makes it easy to broadcast on the fly an existing notebook by simply starting a *second* ",
      "notebook server in the same directory as the first, but in read-only mode.  This can be done without having",
      "to configure a password first (which requires calling a hashing function and editing a configuration file)."
     ]
    },
    {
     "cell_type": "code",
     "collapsed": true,
     "input": [],
     "language": "python",
     "outputs": []
    }
   ]
  }
 ]
}
nbformat-5.9.1/tests/test3.ipynb000066400000000000000000000370031445275403000166140ustar00rootroot00000000000000{
 "metadata": {
  "name": ""
 },
 "nbformat": 3,
 "nbformat_minor": 0,
 "worksheets": [
  {
   "cells": [
    {
     "cell_type": "heading",
     "level": 1,
     "metadata": {},
     "source": [
      "nbconvert latex test"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus bibendum felis dictum sodales. Ut suscipit, orci ut interdum imperdiet, purus ligula mollis *justo*, non malesuada nisl augue eget lorem. Donec bibendum, erat sit amet porttitor aliquam, urna lorem ornare libero, in vehicula diam diam ut ante. Nam non urna rhoncus, accumsan elit sit amet, mollis tellus. Vestibulum nec tellus metus. Vestibulum tempor, ligula et vehicula rhoncus, sapien turpis faucibus lorem, id dapibus turpis mauris ac orci. Sed volutpat vestibulum venenatis."
     ]
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Printed Using Python"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "print(\"hello\")"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "hello\n"
       ]
      }
     ],
     "prompt_number": 1
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Pyout"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from IPython.display import HTML\n",
      "HTML(\"\"\"\n",
      "\n",
      "HTML\n",
      "\"\"\")"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "html": [
        "\n",
        "\n",
        "HTML\n"
       ],
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 3,
       "text": [
        ""
       ]
      }
     ],
     "prompt_number": 3
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%javascript\n",
      "console.log(\"hi\");"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "javascript": [
        "console.log(\"hi\");"
       ],
       "metadata": {},
       "output_type": "display_data",
       "text": [
        ""
       ]
      }
     ],
     "prompt_number": 7
    },
    {
     "cell_type": "heading",
     "level": 3,
     "metadata": {},
     "source": [
      "Image"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from IPython.display import Image\n",
      "Image(\"http://ipython.org/_static/IPy_header.png\")"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "png": "iVBORw0KGgoAAAANSUhEUgAAAggAAABDCAYAAAD5/P3lAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAAH3AAAB9wBYvxo6AAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURB\nVHic7Z15uBxF1bjfugkJhCWBsCSAJGACNg4QCI3RT1lEAVE+UEBNOmwCDcjHT1wQgU+WD3dFxA1o\nCAikAZFFVlnCjizpsCUjHQjBIAkQlpCFJGS79fvjdGf69vTsc2fuza33eeaZmeqq6jM9vZw6dc4p\nBUwC+tE+fqW1fqmRDpRSHjCggS40sBxYDCxKvL8KzNBaL21EPoPB0DPIWVY/4NlE0ffzYfhgu+Qx\nGHoy/YFjaK+CcB3QkIIAHAWs3wRZsuhUSs0CXgQeBm7UWi/spn0Z+jA5yxpEfYruqnwYllRic5a1\nMaWv8U5gaT4M19Sx396IAnZLfB/SLkEMhp5O/3YL0AvoAHaKXl8HLlZK3QZcpbWe0lbJDOsaHuDU\n0e4u4JAy2wPk/C1JzrKWArOQ0fUtwH35MOysQxaDwbCO0NFuAXoh6wPjgQeUUvcqpUa0WyCDoQls\nCIwBjgfuAV7KWdY+7RWpmJxlXZezrEdylvXxdstiMKzrGAtCYxwI/EspdZbW+g/tFsbQ67kQuBHY\nFNgseh9FV6vCbUAeWBC9PgBeq2EfS6J2MQOBrRDTe5KdgAdzlvW1fBjeUUP/3UbOsoYBE6OvG7VT\nFoOhL9Af+BUwFLkZpV+DaY6V4UPkRpb1+ncT+m8nGwK/V0oN01qf025hDL2XfBi+DLycLMtZVo6u\nCsKfGnSq8/NheEpqHwOBEcDBwJnAsGhTP2ByzrJG5cPwnQb22Sy+0G4BDIa+RH+t9dmlNiqlFKIk\nJJWGi+jq5JPmq8BbJJQArfXqpkncczlbKbVQa/3rdgtiMNRCPgxXAK8Ar+Qs63LgXmDvaPPGwPeA\nH7VJvCRfbLcABkNfouwUg9ZaAwuj178BlFLvVejzgR4WFviM1npcuQpKqf6IyXIjxLS7GzAWuUnu\nXsO+fqWUellr3ZBJdq/jr9+BDn1uve07O9Rz0y6f8PtGZGgWe53oT6SBkZ/q1/nHZy47aloTRTKU\nIR+Gy3OWNR6Zxtg0Kv4KRkEwGPocxgcBiCwcsSI0F5iOhF+ilPok8C3gVGS+thK/VErdrbWuO2ys\ns/+aLZTuOKbe9krrIUCPUBB0B+PQ1P1bdKe6EzAKQgvJh+GbOct6gkJkxM45y+qXDIWMHBhjBWJe\nPgyDWvaRs6zPIVObAG/nw/DpEvUGAp8E9gGGJzbtl7Os7cvs4skqp0V0Yl8jgcOBjyMDhbmIZeWl\nfBg+UUVfReQsayhwELAnsAXi6/E28BxwTz4MP6iyn92RaSCA+/NhuCwqXx9R4MYhU0MfRTK/AjyW\nD8MFGd0ZDFVhFIQKaK3/BXxfKXUlklTq0xWafAI4Driyu2UzGLqRlygoCArYHJif2H4gcFb0+Z2c\nZW2bD8NV1XScs6yNgH8g/jsAPwCeTmzfFPgjYsnbiez71MUVdnMQcF8V4nyUs6whwB8QX4+0s2Ys\n0yPAt/NhGFbRZ/wbzgO+DaxXotqqnGX9GbigCkXhf5CBCsDngYdzljURGQhsWqLN+znL+iFwdT4M\ndYk6BkNJTJhjlWitQ2Bf4P4qqv848t8wGHor6Yd9+ruHJFkC2BI4rIa+D6egHKwmstYlGAxMQCwH\nrRjEPI5ER5S7ZvcFXsxZ1phKneUsawSi8HyH0soB0bbvAM9Ebaplt5xlnYkct1LKAYiFZhJwSQ19\nGwxrMRaEGtBar1RKfRX4JxIzXortou3PN1mE+YgJsSwaeoLHOQCqUy3QSr9eqZ6G/gq2aYVMhqrY\nOfF5FeJwvJZ8GM7JWdY/gC9HRS7wtyr7Pjrx+e6MqYC3KLbU7Qhck/h+FJIKvRRVjfSREXicU8EH\npgAvIIqLBZwGfC7avl5Uf29KkLOsTZCMq8npj9sQx89no37HIlaAODplNPBIzrJ2z4dhNVlaT0HC\nXwFmIkrAC4if2PaIz8/3KCgn385Z1pX5MJxeRd8Gw1qMglAjWutlSqnTgUcqVP0SzVYQtP5mcMXE\nSvvtUUy9YsK5QEWHy7EnTB6lOtSsFohkqEDOsgYAdqJoagkT9Z8pKAj75yzr4/kwnF2h748ho/GY\nq9J1oqiKLj4JOctKK8Yz8mH4Yrl9VcnHkXVYTsyHoZ8WJWdZNyPThbF5/3M5yzowH4alpi9+T0E5\nWA18Nx+Gf0zVeRG4KmdZ90R9bwCMRKwyX69C5h2j91uA4/JhuCSxbTYwJWdZtwNPIFbifsAFSISZ\nwVA1ZoqhDrTWjyIjjXIc3ApZDIZu4ELgY4nvt5Wody8wJ/qsgBOr6HsihfvOfCRrY7v5dYZyAECk\nGP0ISEZmZYZ55yxrB8SyEXNxhnKQ7Pt64H8TRUfmLGuXKmWeC4xPKQfJvp9CLCJlZTYYymEUhPq5\ntcL2XVsihcHQJHKWtU3Osi5GnAZj5iKWgiKitRouTxQdl7OscnPu0HV64dp8GLY7R8pyxEGxJPkw\nfBcZ9ceUSvN8IoV76upK/UZcgawcG3NKqYopfleFU+gDic/b5SzLWIwNNWFOmPqp5CG9sVJqPa11\nVZ7dBkOL2D1nWcmcBkOR8MFtgM/QdTXJZcCR+TBcXqa/SYj5egAFZ8VMX4ScZe2FRPnEXF2z9M3n\n3nwYVsrtAmK6/0z0uVR4ZXLtivvzYfhGpU7zYbgkZ1k3ACdHRQdWIQsUO3ZmkUzB3Q/xjaolLbeh\nj2MUhDrRWr+mlFpJ+eV5hyIxz4YWs98Fj/Rf8uZbozo0/ZYt7D8rf9ORK9stUw/hU9GrEnMAp1R+\ngph8GL4bzdNPiIpOorSzYtJ68FS1IYPdTLWp3hcnPm+Q3pizrA7E+TCmFn+aZN0dcpY1LB+G5e4b\ny6rM8bA49X39GmQyGMwUQ4NUGnkMrbDd0A3sdeLk4z6cN+89pTtDTWd+gyErF+7pTv5eu+XqJbyK\nTDHsmg/DJ6tsc2ni8+dzljUqXSGaevhmoqjIObFNVBzlV8kQug4W5tbQNl13WGatAv+poW+DoW6M\nBaExPgC2LrO9nHWhpSilDqI4NPMhrfXUJvS9M/DfqeJXtdY3N9p3rex50uQ9lFKT6BrTvoFCXbTX\nyZNfmnrZxHtbLVMP4xng74nvK5DzeD7wfIWRayb5MHwiZ1kzgF0oOCuemar2ZQoK8zLgr7Xup5t4\ns0n9DEl9b0RBSPeV5q0a+jYY6sYoCI1RacnZ91siRXUMAH6eKnsYicdulDOAY1NlpzWh35pRqG9R\nIuGN7uw4AfG878s8nw/DX3RDv5dScGY8NmdZP86HYXJaJzm9cHMp7/s2UHdK9BTpKaxBNbRN163k\nt9Rux05DH8FMMTTGZhW2v9sSKarjbopNk/sqpUY30qlSahCSGS/JCuD6RvqtF6UpMm/HaHTJbYaG\nmQzED/0umRVzlrUZhXwJ0HOmF5pJOlXyxzJrZbNt6rtZP8HQIzAKQp0opTZAlsItxTKtdTnv75YS\nLR7lpYqrjV0vx2EUH4fbtdZtucnpMqOrDjPy6jYii8DkRFHSYnAEhem22cBjrZKrVeTDcCldTf/p\nh345ksrEGprnF2EwNIRREOrnMxW2z2uJFLVxJcXmy2OVUo34ShydUda+EaIq7T2u0SZTY/eSdFY8\nMGdZm0efk86J6/LCQUnFp5pIkZjkcvQz8mH4YZPkMRgawigI9VNp7v7BlkhRA1rr+RQneNqC2hba\nWYtSajiS9z3JXLomaGktq/VllLIUdKqSWe0MjZMPwxlIel8Q/6Zv5CxrGIX8AJ10XU+hFtIRQ+UW\nKWoXyYyTu+Qsa79KDXKWNRpJyx5zZ9OlMhjqxCgIdaCU6g98o0K1npBCNotLM8rcOvuagCRgSXKN\n1rozq3IrCCZNfFkrfRjotWsCaJinUBODK51/tkuuPkTy/DoYOIDCfeb+fBjW4t2/lqhdcmRdbUri\nVnILXS2HZ1WRvfAcCk61K4A/dYdgBkM9GAWhPr5F6XSrIBf6Qy2SpSaidSReShV/XilV7veUIj29\noOkB2fGmXT7x7sCbOGpFf7VZx4A1m0/znG2nehMyc+0bms7NFJxzxwH7J7Y1OvWUPG9/mLOsLRvs\nr6lEaaOT0TtfBB5ITLWsJWdZg3KWdRNwTKL4wnwYzu9mMQ2GqjFhjjWilBqBpJYtx51a66UV6rST\nS+maJz52VvxRdvVilFK7UbzexGNa67Kr+bWS6X+ekPYs79HkLGt34JOI+Xyz6D2d1vfMnGUdini6\nL0C851/Oh2HD+SyaQT4MV+YsaxJyLm1Gwf9gAXBHg93/JNHHtsArOcuajCztPBDYCkkytBXg5sOw\n5QmF8mF4W86yLgK+HxXtC8zKWVaALMm8CslHsicS7RFzL8VhyAZDWzEKQg0opbYE7qd8prPVdF2h\nrSdyLfALYMNE2XFKqR/XsHbEURll62L4Wiv5PuBUqPPF6JXkLuCQbpGoPi4HfohYKGMHWD9axrlu\n8mF4Z7RuwfioaDBwaonqRemQW0U+DH+Qs6xFwHnIFNwQsv+3mMnA8dHiVwZDj8FMMVSJUuow4DkK\na7GX4gqt9cstEKlutNaL6boULMho5tBq2iul+lH8IFuCmJcNfZx8GM6hOCFVU5THfBhOQHxfylkH\n3gY+asb+6iUfhhcCewC3l5BlFbJk/P75MDwqlVTKYOgRKK1rizhSSk2h67ximo1abV5XSi2n9EIk\nz2itx5XYVqnfQcjI7DiqW2XtfeCTUbRA3ex50nWfUrqjeJEcrfcLrpj4SCN9xyilxgDPp4of0Fof\nUEXbg4B/pIqv1FrXnVNh7AmTR3V0qIwwRH1E4E28pd5+De0hZ1m/Bb4bfX0+H4Z7dMM+hgGjkDwC\nS5FpjFk9bR4/Z1mDkGmF4VHR20g4Y3oxJYOhR9EXphg6lFLlVjFbH0mZvDGwCTAayCFe0ntTOZ1y\nzDLgkEaVg1ahtX5BKfUU8OlE8ReUUjtorSstCduzch8YehSR5/6ERFG3nBvRuhE9frXUfBguA6pd\n+Mpg6DH0BQXBBro7o+Ea4Bta66e6eT/N5lK6KggKOAE4u1QDpdTGFOdNmNkLf7uh+zgYcRQEMa+3\nJe22wWBoDOOD0DhLgYla67vaLUgd3ETxglLHRXkeSnEExQ5gbQ9tNPQokis5TsqHoVlbwGDohRgF\noTECYHet9Y3tFqQetNYrKDb/DqN46eYk6emF1UhUhMFAzrImUEhDvgr4VRvFMRgMDWAUhPpYAvwf\n8Bmte31+/8uQBEdJMjMrKqW2o5A2N+YfWusePw9s6F5yltWRs6zxwKRE8RXtyEVgMBiaQ1/wQWgm\neWTe/jqtdU9Zz74htNavKaXuAw5KFB+glBqptZ6Tqj6RQlrYGDO90AfJWdY5wNeQFQwHIAmetk5U\neZFCsiCDwdALMQpCed5AphEC4NF12BHvUroqCAoJ7TwvVS+d++BdJEmPoe+xKRLnn0UeODwfhm3N\nRWAwGBqjLygIbwN/LbNdI1MGH6ReL/eWkMUmcDeSeGa7RNlRSqnzdZQoQym1C7Bzqt11NWReNKxb\nzEMU6GHAesBiYCaSLOviaF0Cg8HQi+kLCsLrWuvT2y1ET0ZrvUYp5SG57mO2Bz4LPB59/2ZRQ5P7\noM+SD8OLgYvbLYfBYOg+jJOiIeZKxOs8STJiIb28daC1/lf3imQwGAyGdmEUBAMA0XTKraniI5VS\nA6O0zOnloI31wGAwGNZhjIJgSHJp6vtgJBNlehW65cANLZHIYDAYDG3BKAiGtWitHwVeShV/muLF\nuW7VWi9qjVQGg8FgaAd9wUnRUBuXAn9IfN8f+FyqTo/OfbDnSX8brDpXnqEUe2ropzQvdtDx66ev\nGN9XolIMPQDb9T8LrBd4zsPtlsXQe7Bd/0BgQeA5QbtlMQqCIc21wC+ADaPv6WWu5wAPtVKgWtjt\n6Os2XG/9jhdQjIzTQ2rFF9bQecy4E2/I9UQlwXb9LYDDK1R7K/Cc21shj6FxbNcfDjwGKNv1Rwae\n83q7ZWo2tusPBb6ELGW9BbAICX99Gngs8Jx0hlZDBWzXHwvcC6ywXX9o4DlL2ymPURAMXdBaL1ZK\n+ZRItwz8Jc6N0BMZMFB9GxiZsWnzTjrPAH7QWomqYgTF/h9pngC6RUGwXf+XwC2B50ztjv57M7br\nXwJMCjxneo1NP0SWgAfJq7LOYLv+esAFwOkUL9wWM912/d0Dz+lsnWQ9A9v1BwEXAT8PPKfWVOML\nkPVt3kNWQm0rxgfBkEWph5UG/tJCOWqnQ40ttUkrvWcrRamWwHOmAZsguSfGAi9Hmy5AUhgPAz7f\nHfu2XX8k8ENgx+7ovzdju/4uwP9D/peaCDxnCbANsF3gOYubLVu7sF1/AHAHcBaiHDwI/C+ywNsE\n4KfA68BdfVE5iNgbOBmxqtRE4Dn/BoYDnwg8Z02zBasVY0EwFKG1fkEp9RTioJjkIa11zzaVarYq\nvVFt2TpBaiN6oCwB5tiu/2FUPCvwnLTTaLM5oJv77800dGwCz1kXHXkvRNKydwI/Cjzn1+kKtuuf\ni2TX7Ks0et681yxBGsUoCIZSBBQrCL0h98EbdW7rddiuPwoYFJu/bdffFNgL2BZ4DZgWKR5ZbRWS\n2+KIqGiE7fpjUtXmlrtZRdaHscBAYDowM/CckimWbdffFfgw8JzXou/9kfUccojV5MXAcz4s0XYw\nsCsymu8PzAVmBJ7zVqn9pdoPRVKF7wSsAN4EgqzRve36HcAoZDEqgO0zjs3rged8kGo3gOJ05ADT\ns0bTkan+k9HXGaVGjNFxykVf81nH2Hb9Ich/MRJJeT291H9fL7brj6CwANfPspQDgOi3rijRx/rI\nb8kB7wPPBZ4zL6Ne/JvfCDzn/WhufhvgvsBzVkR1dgN2AR4JPGduom38P7wXeM7c6FzfCfgU4iMR\nlFLebNfPIefXzMBzikz8tusPQyx676bljmTeCfhyVLST7frp//TV9Dluu/6GwOhUvTWB58zIkjFq\nsykyNfmfwHMW2K7fLzoWeyDTFPnAc14t1T7qYwNgT+Rc/wi5ZyT/N20UBEMRSqn+wNdTxQspTqTU\n41BaP6yVOipzGzzSYnG6m6uBz0YPv7OQm3dytc35tuuflHZutF3/BuArwEaJ4p/QNdU2wGnAH9M7\njRSTG5CbS5LQdv2joymTLKYBzwHjbNc/DomW2TCxfbXt+sMCz3k/sa8RwM+Qh/X6qf5W2q4/CTit\nzMN1OPB7CopQktW2658YeM5fEvXvRKZzBiXqZaWUPha4JlW2NfB8Rt0hiANfmjWIuf5jiLPfvVm/\nAfmvbgNmB54zKrkheuD+Bjg11Wap7fpnBJ5TybelFk4E+iE+Fb+ptbHt+scg//nGqfJbgeMDz1mY\nKN4UOZYX2q7fSWHhuNdt198ZOBc4MypbbLv+5wPPeTb6PiJqe5ft+ichx3WXRN8rbdc/OfCcrGis\nR4ChiHKSlSn2f4BzkOvitMRvCKJ9DEzU9TPafwGZlkkyBvExSrKUrtdnmoOBycA5tus/iCyat3li\nu7Zd/0rk2ihS1mzXPwT4E3LulaLTKAiGLL6EaMlJbtBat91pphIjFw289t9DVh4N7Jva9EKnWnpJ\nG0RqBXcjCa08YCqy/PJE4L8A33b9HQPPeTNR/0bgvujzGchoywPSq5U+nd6R7fp7IDfRjYDrEE99\nDeyHrPb5lO364xI36zTb2q4/AUnt/SSyLHQHMvJZklQOIhYChyCLid2FWBoGIQrDfwGnAP8Gskzd\nVvSbBgPvIMdpJjLHuxdikXgg1ewa4Jbo84+BHRAFI/3gT9/QQZa+/iIy9zwccVQrSeA5nbbrX4s8\ncI6htIIQK7xdFJLIAvEEYjmYBlyP/E4LeXj92Xb94YHnnFtOjhrYJ3q/vtbpE9v1fwqcjYxUL0GO\n51bI//g1YIzt+mNTSgJIivfNEIXgBOThfx0ySv8Nct7vgzgfj0+1HQf8E5iPKM/vI+vLHA9cZbs+\nJZSEevgDBZ++3yIKzgVI1FeSrCnD6ci0zebAJxCfjmoZjxzXPPBL5By0gW8jCt3sqHwtkYL1N0RB\n/R2ymOG2yHE5CLFAHAu8ahQEQxbfyijrDdML3HTTkWvUBRfsb88bPb6TzjEK+oHKL184YHL+Jmdl\nu+XrJsYBhwaec0dcYLu+hzw0dkcu/AvjbUmLgu36DqIgPB54zuQq9nURMgI8LjnyBibZrj8z2s/l\ntuvvVcJJbWvkXDoi8JzbKu0s8JxFtut/IqXgAPzOdv0/IiPnb5KhICAjpMGIEjAhPV1iu35HWsbA\nc25ObD8ZURAeqibENBqpTYnark8FBSHiakRBOMx2/cHpB29kSv4KooSlLRYnIcrBHcBXk7/Fdv0b\ngReAM23Xvz7wnJlVyFIJK3qfXUsj2/U/jiiiq4B9ktEytuv/Fhlpfx2xEnw31XxHYLfAc6bbrv8k\ncny/Bnwz8Jy/2q6/DTLd9F8Zu94ceXAeEHhOvM7MNbbrT0UU4vNs15+c2FY3gedcm/hNP0EUhDvL\nKMrJtkuIFPboWNWiIOSAO4HDE7/Dj67FSxEn21+m2pyOWDpuCDxn7fG2Xf8e4F1EIVsceE5oohgM\nXVBKjURuSEke11qXMhv3OPR553VO9Sb407yJZwTexO8FnnNV/qYj11XlAOCfSeUA1s4D/y36mp7f\nrAvb9fdGLDMzU8pBzMXIg2wsMhLKQiFhgxWVg5gM5SDm+uh9VHqD7fr7IlaNFcAJWb4UPcHLPvCc\n2YgVZn3gyIwq30AsQg8lQ+aiefUfR1/PzlB08sD9Udusfmsi2t+Q6GutjspnIE6L16dDaSN/irMR\np8dTbddPOxK/nwgxTZr8747e30SsEkNL7PvXGQrAVYgvwggK/gK9mXMyfuON0fvWkY9Dkp2i97uT\nhYHnLKNgURsDxknRUMz5FJ8XP22DHIbqSc9pxsSOW8ObtJ89ovdXbNcvpQC8j4zcdiTbnAoy4q2b\n6Ia3CYV5/Y0zqsXOf4/WEYveaq5GQuOOQaZekhydqJNkW2BLZF2UzhL/R+xE2XAIa+A52nb9lUho\nY63hd7GD5d1ZGwPPmW27/iuIUrkLXc/n9xP13rZd/yNgVezoF8n1NjAyyyKETGGl97fGdv1/IlaL\n3h7e+06WM2PgOQtt11+GTMcNo6vVJ1aWsyK+4nvFQjAKgiGBUmoshfnOmGe11vdl1Tf0GOaUKI9v\nlqrE9lqJb6b/Hb3KsU2Zba/VslPb9bdDfA0ORLz0N62iWWxVqMkc3iZuRuawP2u7/g6JKI9RSCTR\nYoodhOP/YgNKK2Ix2zZJzjnINMN2NbaL/4uiaIUE/0EUhB3pqiCkMwl2IscjXZZFJ/B2iW1xRtWR\nZWTqDcwps63U9f8Q0TSN7fp/iK0PtuvviPjmrCHyR1qrICilNkTmHjZDLsDke/JzOtwnzY1KqXcR\nR4cFiBab9XlRT87I19dQSo1GNPz0tJOxHvR8mhrOVobB0XuAOBiWo1zmwaqdXW3X3x+4BzGVv4SM\npN9AnPEg21McxMIArTs2dRN4zoe26/8NOA6xGJwfbYqV9b8GnrM81Sz+Lz5A0qOXo2y4Ww3MoT4F\nIY4+KTfNF58TaXN4VthstVNDitLKcdxvOjKmEj0tv0M953fs87E3Eul0B2JliBflOzfwnFcA+iul\n5iEmwQFNEBaK569L0amUWggcqrXO8gg2FKHG2CdW4Uem9XvBlUflu7RUaiByU3lPa92ZKN8cSav8\nfUQBTHKr1rrqueIsxp18/eg1azrLjSYB6NfRsY3G6Is9nDjDYxh4zundvbMotvtm5N50duA5P09t\nT0faJIkfirU+zNrF1YiC4FBQECZE73/JqB//F+u14r+ImIVEOB1iu/6ZNfhwzEamp7YuU2e7RN1m\noZBnW5YVIfZ1qNWfotw51yuIph++hET0bAkcikwpTAEuCjxnSly3PzIP0a8NcnYgD6SBlSoaIhQX\nV2UtVup24LBU6S7IyG+NUuodZP52awojrTSvIjeshlij9XdQKh2jXYRRDtpGfOCruQfEpmzbdn0V\ndP9iPLsgjnEryI67Lzd/PCt6/5Tt+v3LJXAqQ/z7ut2ZO/Ccx23XfxUYZbt+7D8xCngl8Jwsa80s\nZBS8ke36O7cg4ybA5UgegJ0QE/XN5auvZRaiIMQRF12wXX8TCv9ls6eERpOtIMR+EXNS5YsRh8dS\nTo/V+CzUck21i6uR5++4wHNeKFXJRDH0PfoR5fqmtHKwDDhCa73O5JA3lCSeF04v6Z3FPRTMzBO7\nS6AE8Q12PbomgYn5Xpm29yMPhu2RUK96iKMn9q6zfa38JXo/NHoly7oQeM5K4Iro60+jKINuJVJC\nYu/439uuX805A4VkWyfbrp+V/MdFnOmeCmpfFKsSRYMc2/U/DeyG3OfSjpOx5WmfVHmcuXFcFfus\n5ZpqObbrb45EtswqpxyAcVI0FDMbOFxrXeT9a+heopvnEArzolvashT0wmbEapdgGpIU5XDb9R9F\nYqrXQyyL8wPPeTeuGHjOMtv1T0VuqldH6W//jigNmyHOcAcBgwPPcZog20xkRLcJ8DPb9S9CRqM7\nI7kDvoDE1hfdxwLPWWy7/plI7oCLbNffHXm4zUQeRtsjGRP/EXhOKSfcABkpj49i5+9G/putgHmB\n5yxIN4iSF21C14V6Rtiu/yYSW15uHv4a4P8oKAedlPcvOAv4KmItfCTKKfAS8v8NR1ILHwnsl5GA\nqF7ORdYaGA48HGWyfBqYgViDRwCfQR72PkDgOU9E2TvHI4m0TgeeRczb30DyH2iKcyA0ymrgWNv1\nFyDK1NvIQ3tStN3LCH+9HUl29UPb9echFo8BUbtLEKfJtJ9EmgA59ifbrj8bCR3cGDlvZqdTLcPa\n9NCbUMhs2GFLKvPFSAKxZl7/CxEL8pgoA+QMxD+kE3HenAHcHnjOGmNB6Dt8iGjHWSFKK4HHkcQr\nOxvloLXYrr+77fqrEIejNyiE6P0WccZbabv+lFLtG+Ry5AY/BHkYfRDtR9M79QAAA3FJREFUcwYS\nNdCFwHPuQR6a7wHfAR5GMhk+i9xcT6G6KIOKBJ6zFBn9r0GUmBlIWN9ziHf/5yjO/phsfy2yqt4i\nxOJxF3INTI9k/Q7ZoV4xv0PC5LZCci4sQm6g08kYHdquvxy5lt4DwsSmF5EENCts1//Idv3M9LbR\negJTkEx4NvBA1joFifqLIjkeR6wcfwdeQfIFTEEcjHNU79RXkShvw95Ixs5+yOj/KuSh+ATiAHcq\nxb4fxwOXRfJMQc6zlxGF6B3g4MBznmmWnBFzEUfP0xDFcCGiAG+JHKushESXIdanjRBF4l3EInAj\n8vuOqWK/5yNRGaOQFNkfIhkOX6CQgwAA2/W3jkI3V0T7ejjatAFyXb2PXP/LbVnroWGi6bbzo697\nIlaWk5Br93wkk+jztusP7o94Lna7eaoMZU0cVXIAped7eqGZfP2ZqmPFl+ptrVf3n19UpvVMYLRS\nagBywxuEjLwWAe9qrTMXV2mUzs7OP/Xrp+6qt33Hmn5Zue3XNeZTOVoky5nqKiQkrNT883Qk3WvJ\nsMLAc1bbrv9Z5AH6KWRkOB+5wRWlWo7a3Ga7/mOIomAho/GFyI30YeDREru7ELlOq07TG3jONbbr\nT0Nu9KOQm+i/gFsDz3nTdv2fI2FbpdpfHnlpH4LcnHdAlIz5yLErqXgFnvOR7fo28lDYE7lu3kKO\nTdZ9K52xrhTl7knnUVB6SqVeTsr4apQU6lDEbG4hCsFbROsRBE1ebjrwnNB2/XGIGf5gRBkYhPyv\n7yDpjR9MtVkOnGK7/vWIgrFrVPcF4O8ZKbaXIuduWkH6KfL/JbkEsWClfWK2CDzHt10/jzhXjkGO\nyzNIZEiRD00ga3ocaLv+kUh2xo8hSuVURKmIUyiXVGYCWVzKQlJD7xrJNg85b9LX8RLgF6X6SpFU\n9Cpe28gaJgORqEEAbNffDLlvHIQoAndR8NEYilwjExD/nwuUiTQ0GAwGw7qC7fqjEUvKqsBzmhWd\nt05gu/5pyNoifw48J9N5PForxQeeNFMMBoPBYDD0DWL/llvK1In9jt4zCoLBYDAYDH2DePo5MwrJ\ndv0hFPwTnjBRDAaDwWAw9A3+hPgOHRPl25iK+FhsiuR4OARx0Lwf+J1REAwGg8Fg6AMEnvNklL78\nHMRRca/E5hVINNIVwI2B56z6/3ExLRI31pXNAAAAAElFTkSuQmCC\n",
       "prompt_number": 6,
       "text": [
        ""
       ]
      }
     ],
     "prompt_number": 6
    }
   ],
   "metadata": {}
  }
 ]
}
nbformat-5.9.1/tests/test3_no_metadata.ipynb000066400000000000000000000367431445275403000211620ustar00rootroot00000000000000{
 "nbformat": 3,
 "nbformat_minor": 0,
 "worksheets": [
  {
   "cells": [
    {
     "cell_type": "heading",
     "level": 1,
     "metadata": {},
     "source": [
      "nbconvert latex test"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus bibendum felis dictum sodales. Ut suscipit, orci ut interdum imperdiet, purus ligula mollis *justo*, non malesuada nisl augue eget lorem. Donec bibendum, erat sit amet porttitor aliquam, urna lorem ornare libero, in vehicula diam diam ut ante. Nam non urna rhoncus, accumsan elit sit amet, mollis tellus. Vestibulum nec tellus metus. Vestibulum tempor, ligula et vehicula rhoncus, sapien turpis faucibus lorem, id dapibus turpis mauris ac orci. Sed volutpat vestibulum venenatis."
     ]
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Printed Using Python"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "print(\"hello\")"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "hello\n"
       ]
      }
     ],
     "prompt_number": 1
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Pyout"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from IPython.display import HTML\n",
      "HTML(\"\"\"\n",
      "\n",
      "HTML\n",
      "\"\"\")"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "html": [
        "\n",
        "\n",
        "HTML\n"
       ],
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 3,
       "text": [
        ""
       ]
      }
     ],
     "prompt_number": 3
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%javascript\n",
      "console.log(\"hi\");"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "javascript": [
        "console.log(\"hi\");"
       ],
       "metadata": {},
       "output_type": "display_data",
       "text": [
        ""
       ]
      }
     ],
     "prompt_number": 7
    },
    {
     "cell_type": "heading",
     "level": 3,
     "metadata": {},
     "source": [
      "Image"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from IPython.display import Image\n",
      "Image(\"http://ipython.org/_static/IPy_header.png\")"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "png": "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\n",
       "prompt_number": 6,
       "text": [
        ""
       ]
      }
     ],
     "prompt_number": 6
    }
   ],
   "metadata": {}
  }
 ]
}
nbformat-5.9.1/tests/test3_no_min_version.ipynb000066400000000000000000000001621445275403000217140ustar00rootroot00000000000000{
 "metadata": {
  "name": ""
 },
 "nbformat": 3,
 "worksheets": [
  {
   "metadata": {},
   "cells": []
  }
 ]
}
nbformat-5.9.1/tests/test3_no_worksheets.ipynb000066400000000000000000000001111445275403000215540ustar00rootroot00000000000000{
 "metadata": {
  "name": ""
 },
 "nbformat": 3,
 "nbformat_minor": 0
}
nbformat-5.9.1/tests/test3_worksheet_with_no_cells.ipynb000066400000000000000000000001701445275403000236130ustar00rootroot00000000000000{
 "metadata": {
  "name": ""
 },
 "nbformat": 3,
 "nbformat_minor": 0,
 "worksheets": [
  {
   "metadata": {}
  }
 ]
}
nbformat-5.9.1/tests/test4.5.ipynb000066400000000000000000000373121445275403000167630ustar00rootroot00000000000000{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "2fcdfa53",
   "metadata": {},
   "source": [
    "# nbconvert latex test"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0bc81532",
   "metadata": {},
   "source": [
    "**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus bibendum felis dictum sodales. Ut suscipit, orci ut interdum imperdiet, purus ligula mollis *justo*, non malesuada nisl augue eget lorem. Donec bibendum, erat sit amet porttitor aliquam, urna lorem ornare libero, in vehicula diam diam ut ante. Nam non urna rhoncus, accumsan elit sit amet, mollis tellus. Vestibulum nec tellus metus. Vestibulum tempor, ligula et vehicula rhoncus, sapien turpis faucibus lorem, id dapibus turpis mauris ac orci. Sed volutpat vestibulum venenatis."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bb687f78",
   "metadata": {},
   "source": [
    "## Printed Using Python"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "38f37a24",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello\n"
     ]
    }
   ],
   "source": [
    "print(\"hello\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a1f70963",
   "metadata": {},
   "source": [
    "## Pyout"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "8206b3b9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "\n",
       "HTML\n"
      ],
      "text/plain": [
       ""
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import HTML\n",
    "\n",
    "HTML(\n",
    "    \"\"\"\n",
    "\n",
    "HTML\n",
    "\"\"\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "88d8965b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "console.log(\"hi\");"
      ],
      "text/plain": [
       ""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%javascript\n",
    "console.log(\"hi\");"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "34334c4f",
   "metadata": {},
   "source": [
    "### Image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "8b414a68",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       ""
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import Image\n",
    "\n",
    "Image(\"http://ipython.org/_static/IPy_header.png\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
nbformat-5.9.1/tests/test4.ipynb000066400000000000000000000417701445275403000166230ustar00rootroot00000000000000{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# nbconvert latex test"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus bibendum felis dictum sodales. Ut suscipit, orci ut interdum imperdiet, purus ligula mollis *justo*, non malesuada nisl augue eget lorem. Donec bibendum, erat sit amet porttitor aliquam, urna lorem ornare libero, in vehicula diam diam ut ante. Nam non urna rhoncus, accumsan elit sit amet, mollis tellus. Vestibulum nec tellus metus. Vestibulum tempor, ligula et vehicula rhoncus, sapien turpis faucibus lorem, id dapibus turpis mauris ac orci. Sed volutpat vestibulum venenatis."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Printed Using Python"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello\n"
     ]
    }
   ],
   "source": [
    "print(\"hello\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Pyout"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "\n",
       "HTML\n"
      ],
      "text/plain": [
       ""
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import HTML\n",
    "\n",
    "HTML(\n",
    "    \"\"\"\n",
    "\n",
    "HTML\n",
    "\"\"\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "console.log(\"hi\");"
      ],
      "text/plain": [
       ""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%javascript\n",
    "console.log(\"hi\");"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": [
       "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\n"
      ],
      "text/plain": [
       ""
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import Image\n",
    "\n",
    "Image(\"http://ipython.org/_static/IPy_header.png\")"
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 0
}
nbformat-5.9.1/tests/test4custom.ipynb000066400000000000000000000014771445275403000200560ustar00rootroot00000000000000{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "application/vnd.raw.v1+json": {
       "apples": [
        "🍎",
        "🍏"
       ],
       "bananas": 2,
       "oranges": "apples"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import IPython\n",
    "\n",
    "bundle = {}\n",
    "bundle['application/vnd.raw.v1+json'] = {'apples': ['🍎', '🍏'], 'bananas': 2, 'oranges': 'apples'}\n",
    "\n",
    "IPython.display.display(bundle, raw=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 2
}
nbformat-5.9.1/tests/test4docinfo.ipynb000066400000000000000000000421151445275403000201570ustar00rootroot00000000000000{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# nbconvert latex test"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus bibendum felis dictum sodales. Ut suscipit, orci ut interdum imperdiet, purus ligula mollis *justo*, non malesuada nisl augue eget lorem. Donec bibendum, erat sit amet porttitor aliquam, urna lorem ornare libero, in vehicula diam diam ut ante. Nam non urna rhoncus, accumsan elit sit amet, mollis tellus. Vestibulum nec tellus metus. Vestibulum tempor, ligula et vehicula rhoncus, sapien turpis faucibus lorem, id dapibus turpis mauris ac orci. Sed volutpat vestibulum venenatis."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Printed Using Python"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello\n"
     ]
    }
   ],
   "source": [
    "print(\"hello\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Pyout"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "\n",
       "HTML\n"
      ],
      "text/plain": [
       ""
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import HTML\n",
    "\n",
    "HTML(\n",
    "    \"\"\"\n",
    "\n",
    "HTML\n",
    "\"\"\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "console.log(\"hi\");"
      ],
      "text/plain": [
       ""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%javascript\n",
    "console.log(\"hi\");"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": [
       "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\n"
      ],
      "text/plain": [
       ""
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import Image\n",
    "\n",
    "Image(\"http://ipython.org/_static/IPy_header.png\")"
   ]
  }
 ],
 "metadata": {
  "title": "Test Notebook",
  "authors": [
   {
    "name": "Jean Tester"
   }
  ]
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
nbformat-5.9.1/tests/test4jupyter_metadata.ipynb000066400000000000000000000006551445275403000221030ustar00rootroot00000000000000{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false,
    "jupyter": {
      "outputs_hidden": false,
      "source_hidden": false
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello\n"
     ]
    }
   ],
   "source": [
    "print(\"hello\")"
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 0
}
nbformat-5.9.1/tests/test4jupyter_metadata_timings.ipynb000066400000000000000000000022571445275403000236350ustar00rootroot00000000000000{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2019-08-26T17:50:29.604738Z",
     "iopub.status.busy": "2019-08-26T17:50:29.603423Z",
     "iopub.status.idle": "2019-08-26T17:50:29.628032Z",
     "shell.execute_reply": "2019-08-26T17:50:29.623438Z",
     "shell.execute_reply.started": "2019-08-26T17:50:29.604616Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1 + 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.0"
  },
  "record_timing": true
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
nbformat-5.9.1/tests/test4plus.ipynb000066400000000000000000000435521445275403000175270ustar00rootroot00000000000000{
 "extra": "future",
 "cells": [
  {
   "id": "future-1",
   "cell_type": "markdown",
   "extra": 5,
   "metadata": {},
   "source": [
    "# nbconvert latex test"
   ]
  },
  {
   "id": "future-2",
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus bibendum felis dictum sodales. Ut suscipit, orci ut interdum imperdiet, purus ligula mollis *justo*, non malesuada nisl augue eget lorem. Donec bibendum, erat sit amet porttitor aliquam, urna lorem ornare libero, in vehicula diam diam ut ante. Nam non urna rhoncus, accumsan elit sit amet, mollis tellus. Vestibulum nec tellus metus. Vestibulum tempor, ligula et vehicula rhoncus, sapien turpis faucibus lorem, id dapibus turpis mauris ac orci. Sed volutpat vestibulum venenatis."
   ]
  },
  {
   "id": "future-3",
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Printed Using Python"
   ]
  },
  {
   "id": "future-4",
   "cell_type": "code",
   "execution_count": 1,
   "future": "yes",
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "extra": "future",
     "output_type": "stream",
     "text": [
      "hello\n"
     ]
    }
   ],
   "source": [
    "print(\"hello\")"
   ]
  },
  {
   "id": "future-5",
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Pyout"
   ]
  },
  {
   "id": "future-6",
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "\n",
       "HTML\n"
      ],
      "text/plain": [
       ""
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import HTML\n",
    "\n",
    "HTML(\n",
    "    \"\"\"\n",
    "\n",
    "HTML\n",
    "\"\"\"\n",
    ")"
   ]
  },
  {
   "id": "future-7",
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "console.log(\"hi\");"
      ],
      "text/plain": [
       ""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%javascript\n",
    "console.log(\"hi\");"
   ]
  },
  {
   "id": "future-8",
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Image"
   ]
  },
  {
   "id": "future-9",
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": [
       "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\n"
      ],
      "extra": "yes",
      "text/plain": [
       ""
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "extra": "yes",
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import Image\n",
    "\n",
    "Image(\"http://ipython.org/_static/IPy_header.png\")"
   ]
  },
  {
   "id": "future-10",
   "cell_type": "future cell",
   "metadata": {},
   "key": "value"
  },
  {
   "id": "future-11",
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello\n"
     ]
    },
    {
     "output_type": "future output",
     "some key": [
      "some data"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello again\n"
     ]
    }
   ],
   "source": [
    "future_output()"
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 99
}
nbformat-5.9.1/tests/test_api.py000066400000000000000000000071241445275403000166720ustar00rootroot00000000000000"""Test the APIs at the top-level of nbformat"""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

import json
import os
import pathlib
from tempfile import TemporaryDirectory
from typing import Any, Dict

from jsonschema import ValidationError
from pep440 import is_canonical

from nbformat import __version__ as nbf_version
from nbformat import current_nbformat, read, write, writes
from nbformat.reader import get_version
from nbformat.validator import isvalid

from .base import TestsBase


def test_canonical_version():
    assert is_canonical(nbf_version)


class TestAPI(TestsBase):
    def test_read(self):
        """Can older notebooks be opened and automatically converted to the current
        nbformat?"""

        # Open a version 2 notebook.
        with self.fopen("test2.ipynb", "r") as f:
            nb = read(f, as_version=current_nbformat)

        # Check that the notebook was upgraded to the latest version automatically.
        (major, minor) = get_version(nb)
        self.assertEqual(major, current_nbformat)

    def test_write_downgrade_2(self):
        """dowgrade a v3 notebook to v2"""
        # Open a version 3 notebook.
        with self.fopen("test3.ipynb", "r") as f:
            nb = read(f, as_version=3)

        jsons = writes(nb, version=2)
        nb2 = json.loads(jsons)
        (major, minor) = get_version(nb2)
        self.assertEqual(major, 2)

    def test_read_write_path(self):
        """read() and write() take filesystem paths"""
        path = os.path.join(self._get_files_path(), "test4.ipynb")
        nb = read(path, as_version=4)

        with TemporaryDirectory() as td:
            dest = os.path.join(td, "echidna.ipynb")
            write(nb, dest)
            assert os.path.isfile(dest)

    def test_read_write_pathlib_object(self):
        """read() and write() take path-like objects such as pathlib objects"""
        path = pathlib.Path(self._get_files_path()) / "test4.ipynb"
        nb = read(path, as_version=4)

        with TemporaryDirectory() as td:
            dest = pathlib.Path(td) / "echidna.ipynb"
            write(nb, dest)
            assert os.path.isfile(dest)

    def test_capture_validation_error(self):
        """Test that validation error can be captured on read() and write()"""
        validation_error: Dict[str, Any] = {}
        path = os.path.join(self._get_files_path(), "invalid.ipynb")
        nb = read(path, as_version=4, capture_validation_error=validation_error)
        assert not isvalid(nb)
        assert "ValidationError" in validation_error
        assert isinstance(validation_error["ValidationError"], ValidationError)

        validation_error = {}
        with TemporaryDirectory() as td:
            dest = os.path.join(td, "invalid.ipynb")
            write(nb, dest, capture_validation_error=validation_error)
            assert os.path.isfile(dest)
            assert "ValidationError" in validation_error
            assert isinstance(validation_error["ValidationError"], ValidationError)

        # Repeat with a valid notebook file
        validation_error = {}
        path = os.path.join(self._get_files_path(), "test4.ipynb")
        nb = read(path, as_version=4, capture_validation_error=validation_error)
        assert isvalid(nb)
        assert "ValidationError" not in validation_error

        validation_error = {}
        with TemporaryDirectory() as td:
            dest = os.path.join(td, "test4.ipynb")
            write(nb, dest, capture_validation_error=validation_error)
            assert os.path.isfile(dest)
            assert "ValidationError" not in validation_error
nbformat-5.9.1/tests/test_convert.py000066400000000000000000000047161445275403000176050ustar00rootroot00000000000000"""Tests for nbformat.convert"""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

from nbformat import current_nbformat
from nbformat.converter import convert
from nbformat.reader import get_version, read
from nbformat.validator import ValidationError, isvalid, validate

from .base import TestsBase


class TestConvert(TestsBase):
    def test_downgrade_3_2(self):
        """Do notebook downgrades work?"""

        # Open a version 3 notebook and attempt to downgrade it to version 2.
        with self.fopen("test3.ipynb", "r") as f:
            nb = read(f)
        nb = convert(nb, 2)

        # Check if downgrade was successful.
        (major, minor) = get_version(nb)
        self.assertEqual(major, 2)

    def test_upgrade_2_3(self):
        """Do notebook upgrades work?"""

        # Open a version 2 notebook and attempt to upgrade it to version 3.
        with self.fopen("test2.ipynb", "r") as f:
            nb = read(f)
        nb = convert(nb, 3)

        # Check if upgrade was successful.
        (major, minor) = get_version(nb)
        self.assertEqual(major, 3)

    def test_upgrade_downgrade_4_3_4(self):
        """Test that a v4 notebook downgraded to v3 and then upgraded to v4
        passes validation tests"""
        with self.fopen("test4.ipynb", "r") as f:
            nb = read(f)
        validate(nb)
        nb = convert(nb, 3)
        validate(nb)
        nb = convert(nb, 4)
        self.assertEqual(isvalid(nb), True)

    def test_upgrade_3_4__missing_metadata(self):
        with self.fopen("test3_no_metadata.ipynb", "r") as f:
            nb = read(f)

        with self.assertRaisesRegex(ValidationError, r"could not be converted.+metadata"):
            convert(nb, 4)

    def test_open_current(self):
        """Can an old notebook be opened and converted to the current version
        while remembering the original version of the notebook?"""

        # Open a version 2 notebook and attempt to upgrade it to the current version
        # while remembering it's version information.
        with self.fopen("test2.ipynb", "r") as f:
            nb = read(f)
        (original_major, original_minor) = get_version(nb)
        nb = convert(nb, current_nbformat)

        # Check if upgrade was successful.
        (major, minor) = get_version(nb)
        self.assertEqual(major, current_nbformat)

        # Check if the original major revision was remembered.
        self.assertEqual(original_major, 2)
nbformat-5.9.1/tests/test_nbformat.py000066400000000000000000000022451445275403000177300ustar00rootroot00000000000000import pytest

from nbformat import read
from nbformat.validator import ValidationError


def test_read_invalid_iowrapper(tmpdir):
    ipynb_filepath = tmpdir.join("empty.ipynb")
    ipynb_filepath.write("{}")

    with pytest.raises(ValidationError) as excinfo, ipynb_filepath.open() as fp:
        read(fp, as_version=4)
    assert "cells" in str(excinfo.value)


def test_read_invalid_filepath(tmpdir):
    ipynb_filepath = tmpdir.join("empty.ipynb")
    ipynb_filepath.write("{}")

    with pytest.raises(ValidationError) as excinfo:
        read(str(ipynb_filepath), as_version=4)
    assert "cells" in str(excinfo.value)


def test_read_invalid_pathlikeobj(tmpdir):
    ipynb_filepath = tmpdir.join("empty.ipynb")
    ipynb_filepath.write("{}")

    with pytest.raises(ValidationError) as excinfo:
        read(ipynb_filepath, as_version=4)
    assert "cells" in str(excinfo.value)


def test_read_invalid_str(tmpdir):
    with pytest.raises(OSError) as excinfo:
        read("not_exist_path", as_version=4)
    assert "No such file or directory" in str(excinfo.value)


def test_read_invalid_type(tmpdir):
    with pytest.raises(OSError) as excinfo:
        read(123, as_version=4)
nbformat-5.9.1/tests/test_reader.py000066400000000000000000000035421445275403000173630ustar00rootroot00000000000000"""
Contains tests class for reader.py
"""
# -----------------------------------------------------------------------------
#  Copyright (C) 2013  The IPython Development Team
#
#  Distributed under the terms of the BSD License.  The full license is in
#  the file LICENSE, distributed as part of this software.
# -----------------------------------------------------------------------------

# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------

from nbformat.reader import get_version, read
from nbformat.validator import ValidationError

from .base import TestsBase

# -----------------------------------------------------------------------------
# Classes and functions
# -----------------------------------------------------------------------------


class TestReader(TestsBase):
    def test_read(self):
        """Can older notebooks be opened without modification?"""

        # Open a version 3 notebook.  Make sure it is still version 3.
        with self.fopen("test3.ipynb", "r") as f:
            nb = read(f)
        (major, minor) = get_version(nb)
        self.assertEqual(major, 3)

        # Open a version 2 notebook.  Make sure it is still version 2.
        with self.fopen("test2.ipynb", "r") as f:
            nb = read(f)
        (major, minor) = get_version(nb)
        self.assertEqual(major, 2)

    def test_read_fails_on_missing_worksheets(self):
        with self.fopen("test3_no_worksheets.ipynb", "r") as f, self.assertRaisesRegex(
            ValidationError, r"worksheets"
        ):
            nb = read(f)

    def test_read_fails_on_missing_worksheet_cells(self):
        with self.fopen("test3_worksheet_with_no_cells.ipynb", "r") as f, self.assertRaisesRegex(
            ValidationError, r"cells"
        ):
            nb = read(f)
nbformat-5.9.1/tests/test_sign.py000066400000000000000000000221461445275403000170620ustar00rootroot00000000000000"""Test Notebook signing"""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

import codecs
import copy
import os
import shutil
import sys
import tempfile
import time
import unittest
from subprocess import PIPE, Popen

import testpath
from traitlets.config import Config

from nbformat import read, sign, write

from .base import TestsBase


class TestNotary(TestsBase):
    def setUp(self):
        self.data_dir = tempfile.mkdtemp()
        self.notary = sign.NotebookNotary(
            db_file=":memory:",
            secret=b"secret",
            data_dir=self.data_dir,
        )
        with self.fopen("test3.ipynb", "r") as f:
            self.nb = read(f, as_version=4)
        with self.fopen("test3.ipynb", "r") as f:
            self.nb3 = read(f, as_version=3)

    def tearDown(self):
        self.notary.store.close()
        shutil.rmtree(self.data_dir)

    def test_invalid_db_file(self):
        invalid_sql_file = os.path.join(self.data_dir, "invalid_db_file.db")
        with open(invalid_sql_file, "w") as tempfile:
            tempfile.write("[invalid data]")

        invalid_notary = sign.NotebookNotary(
            db_file=invalid_sql_file,
            secret=b"secret",
        )
        invalid_notary.sign(self.nb)
        invalid_notary.store.close()

        testpath.assert_isfile(os.path.join(self.data_dir, invalid_sql_file))
        testpath.assert_isfile(os.path.join(self.data_dir, invalid_sql_file + ".bak"))

    def test_algorithms(self):
        last_sig = ""
        for algo in sign.algorithms:
            self.notary.algorithm = algo
            sig = self.notary.compute_signature(self.nb)
            self.assertNotEqual(last_sig, sig)
            last_sig = sig

    def test_sign_same(self):
        """Multiple signatures of the same notebook are the same"""
        sig1 = self.notary.compute_signature(self.nb)
        sig2 = self.notary.compute_signature(self.nb)
        self.assertEqual(sig1, sig2)

    def test_change_secret(self):
        """Changing the secret changes the signature"""
        sig1 = self.notary.compute_signature(self.nb)
        self.notary.secret = b"different"
        sig2 = self.notary.compute_signature(self.nb)
        self.assertNotEqual(sig1, sig2)

    def test_sign(self):
        self.assertFalse(self.notary.check_signature(self.nb))
        self.notary.sign(self.nb)
        self.assertTrue(self.notary.check_signature(self.nb))

    def test_unsign(self):
        self.notary.sign(self.nb)
        self.assertTrue(self.notary.check_signature(self.nb))
        self.notary.unsign(self.nb)
        self.assertFalse(self.notary.check_signature(self.nb))
        self.notary.unsign(self.nb)
        self.assertFalse(self.notary.check_signature(self.nb))

    def test_cull_db(self):
        # this test has various sleeps of 2ms
        # to ensure low resolution timestamps compare as expected
        dt = 2e-3
        nbs = [copy.deepcopy(self.nb) for i in range(10)]
        for row in self.notary.store.db.execute("SELECT * FROM nbsignatures"):
            print(row)
        self.notary.store.cache_size = 8
        for i, nb in enumerate(nbs[:8]):
            nb.metadata.dirty = i
            self.notary.sign(nb)

        for i, nb in enumerate(nbs[:8]):
            time.sleep(dt)
            self.assertTrue(self.notary.check_signature(nb), "nb %i is trusted" % i)

        # signing the 9th triggers culling of first 3
        # (75% of 8 = 6, 9 - 6 = 3 culled)
        self.notary.sign(nbs[8])
        self.assertFalse(self.notary.check_signature(nbs[0]))
        self.assertFalse(self.notary.check_signature(nbs[1]))
        self.assertFalse(self.notary.check_signature(nbs[2]))
        self.assertTrue(self.notary.check_signature(nbs[3]))
        # checking nb3 should keep it from being culled:
        self.notary.sign(nbs[0])
        self.notary.sign(nbs[1])
        self.notary.sign(nbs[2])
        self.assertTrue(self.notary.check_signature(nbs[3]))
        self.assertFalse(self.notary.check_signature(nbs[4]))

    def test_check_signature(self):
        nb = self.nb
        md = nb.metadata
        notary = self.notary
        check_signature = notary.check_signature
        # no signature:
        md.pop("signature", None)
        self.assertFalse(check_signature(nb))
        # hash only, no algo
        md.signature = notary.compute_signature(nb)
        self.assertFalse(check_signature(nb))
        # proper signature, algo mismatch
        notary.algorithm = "sha224"
        notary.sign(nb)
        notary.algorithm = "sha256"
        self.assertFalse(check_signature(nb))
        # check correctly signed notebook
        notary.sign(nb)
        self.assertTrue(check_signature(nb))

    def test_mark_cells_untrusted(self):
        cells = self.nb.cells
        self.notary.mark_cells(self.nb, False)
        for cell in cells:
            self.assertNotIn("trusted", cell)
            if cell.cell_type == "code":
                self.assertIn("trusted", cell.metadata)
                self.assertFalse(cell.metadata.trusted)
            else:
                self.assertNotIn("trusted", cell.metadata)

    def test_mark_cells_trusted(self):
        cells = self.nb.cells
        self.notary.mark_cells(self.nb, True)
        for cell in cells:
            self.assertNotIn("trusted", cell)
            if cell.cell_type == "code":
                self.assertIn("trusted", cell.metadata)
                self.assertTrue(cell.metadata.trusted)
            else:
                self.assertNotIn("trusted", cell.metadata)

    def test_check_cells(self):
        nb = self.nb
        self.notary.mark_cells(nb, True)
        self.assertTrue(self.notary.check_cells(nb))
        for cell in nb.cells:
            self.assertNotIn("trusted", cell)
        self.notary.mark_cells(nb, False)
        self.assertFalse(self.notary.check_cells(nb))
        for cell in nb.cells:
            self.assertNotIn("trusted", cell)

    def test_trust_no_output(self):
        nb = self.nb
        self.notary.mark_cells(nb, False)
        for cell in nb.cells:
            if cell.cell_type == "code":
                cell.outputs = []
        self.assertTrue(self.notary.check_cells(nb))

    def test_mark_cells_untrusted_v3(self):
        nb = self.nb3
        cells = nb.worksheets[0].cells
        self.notary.mark_cells(nb, False)
        for cell in cells:
            self.assertNotIn("trusted", cell)
            if cell.cell_type == "code":
                self.assertIn("trusted", cell.metadata)
                self.assertFalse(cell.metadata.trusted)
            else:
                self.assertNotIn("trusted", cell.metadata)

    def test_mark_cells_trusted_v3(self):
        nb = self.nb3
        cells = nb.worksheets[0].cells
        self.notary.mark_cells(nb, True)
        for cell in cells:
            self.assertNotIn("trusted", cell)
            if cell.cell_type == "code":
                self.assertIn("trusted", cell.metadata)
                self.assertTrue(cell.metadata.trusted)
            else:
                self.assertNotIn("trusted", cell.metadata)

    def test_check_cells_v3(self):
        nb = self.nb3
        cells = nb.worksheets[0].cells
        self.notary.mark_cells(nb, True)
        self.assertTrue(self.notary.check_cells(nb))
        for cell in cells:
            self.assertNotIn("trusted", cell)
        self.notary.mark_cells(nb, False)
        self.assertFalse(self.notary.check_cells(nb))
        for cell in cells:
            self.assertNotIn("trusted", cell)

    def test_sign_stdin(self):
        def sign_stdin(nb):
            env = os.environ.copy()
            env["JUPYTER_DATA_DIR"] = self.data_dir
            p = Popen(
                [sys.executable, "-m", "nbformat.sign", "--log-level=0"],  # noqa
                stdin=PIPE,
                stdout=PIPE,
                env=env,
            )
            assert p.stdin is not None
            write(nb, codecs.getwriter("utf8")(p.stdin))
            p.stdin.close()
            p.wait()
            self.assertEqual(p.returncode, 0)
            assert p.stdout is not None
            out = p.stdout.read().decode("utf8", "replace")
            p.stdout.close()
            return out

        out = sign_stdin(self.nb3)
        self.assertIn("Signing notebook: ", out)
        out = sign_stdin(self.nb3)
        self.assertIn("already signed: ", out)


def test_config_store():
    store = sign.MemorySignatureStore()

    c = Config()
    c.NotebookNotary.store_factory = lambda: store
    notary = sign.NotebookNotary(config=c)
    assert notary.store is store


class SignatureStoreTests(unittest.TestCase):
    def setUp(self):
        self.store = sign.MemorySignatureStore()

    def test_basics(self):
        digest = "0123457689abcef"
        algo = "fake_sha"
        assert not self.store.check_signature(digest, algo)
        self.store.store_signature(digest, algo)
        assert self.store.check_signature(digest, algo)
        self.store.remove_signature(digest, algo)
        assert not self.store.check_signature(digest, algo)


class SQLiteSignatureStoreTests(SignatureStoreTests):
    def setUp(self):
        self.store = sign.SQLiteSignatureStore(":memory:")  # type:ignore[assignment]
nbformat-5.9.1/tests/test_validator.py000066400000000000000000000273051445275403000201110ustar00rootroot00000000000000"""Test nbformat.validator"""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

import json
import os
import re
from copy import deepcopy

import pytest
from jsonschema import ValidationError

import nbformat
from nbformat import read
from nbformat.json_compat import VALIDATORS
from nbformat.validator import isvalid, iter_validate, validate
from nbformat.warnings import DuplicateCellId, MissingIDFieldWarning

from .base import TestsBase

nb4 = ("test4.ipynb", "test4.5.ipynb")


# Fixtures
@pytest.fixture(autouse=True)
def clean_env_before_and_after_tests():
    """Fixture to clean up env variables before and after tests."""
    os.environ.pop("NBFORMAT_VALIDATOR", None)
    yield
    os.environ.pop("NBFORMAT_VALIDATOR", None)


# Helpers
def set_validator(validator_name):
    os.environ["NBFORMAT_VALIDATOR"] = validator_name


@pytest.mark.parametrize("validator_name", VALIDATORS)
def test_should_warn(validator_name):
    """Test that a v4 notebook witout id emit a warning"""
    set_validator(validator_name)
    with TestsBase.fopen("test4.5.ipynb", "r") as f:
        nb = read(f, as_version=4)

    del nb.cells[3]["id"]
    assert nb.cells[3]["cell_type"] == "code"

    nb_copy = deepcopy(nb)

    with pytest.warns(MissingIDFieldWarning):
        validate(nb)
    assert isvalid(nb) is True


@pytest.mark.xfail(reason="In the future we want to stop warning, and raise an error")
@pytest.mark.parametrize("validator_name", VALIDATORS)
def test_should_not_mutate(validator_name):
    """Test that a v4 notebook without id raise an error and does/not mutate

    Probably should be 2 distinct tests. To enable in the future.
    """
    set_validator(validator_name)
    with TestsBase.fopen("test4.5.ipynb", "r") as f:
        nb = read(f, as_version=4)

    del nb.cells[3]["id"]
    assert nb.cells[3]["cell_type"] == "code"

    nb_deep_copy = deepcopy(nb)
    with pytest.raises(MissingIDFieldWarning):
        validate(nb)

    assert nb == nb_deep_copy

    assert isvalid(nb) is False


def _invalidator_1(nb):
    del nb.cells[3]["id"]


def _invalidator_3(nb):
    nb.cells[3]["id"] = "hey"
    nb.cells[2]["id"] = "hey"


def _invalidator_2(nb):
    nb.cells[3]["id"] = nb.cells[2]["id"]


@pytest.mark.parametrize("validator_name", VALIDATORS)
@pytest.mark.parametrize("invalidator", [_invalidator_1, _invalidator_2])
def test_is_valid_should_not_mutate(validator_name, invalidator):
    """Test that a v4 notebook does not mutate in is_valid, and does note autofix."""
    set_validator(validator_name)
    with TestsBase.fopen("test4.5.ipynb", "r") as f:
        nb = read(f, as_version=4)

    invalidator(nb)
    assert nb.cells[3]["cell_type"] == "code"

    nb_deep_copy = deepcopy(nb)
    assert isvalid(nb) is False

    assert nb == nb_deep_copy


@pytest.mark.parametrize("validator_name", VALIDATORS)
def test_nb2(validator_name):
    """Test that a v2 notebook converted to current passes validation"""
    set_validator(validator_name)
    with TestsBase.fopen("test2.ipynb", "r") as f:
        nb = read(f, as_version=4)
    validate(nb)
    assert isvalid(nb)


@pytest.mark.parametrize("validator_name", VALIDATORS)
def test_nb3(validator_name):
    """Test that a v3 notebook passes validation"""
    set_validator(validator_name)
    with TestsBase.fopen("test3.ipynb", "r") as f:
        nb = read(f, as_version=4)
    validate(nb)
    assert isvalid(nb)


@pytest.mark.parametrize("validator_name", VALIDATORS)
@pytest.mark.parametrize("nbfile", nb4)
def test_nb4(validator_name, nbfile):
    """Test that a v4 notebook passes validation"""
    set_validator(validator_name)
    with TestsBase.fopen(nbfile, "r") as f:
        nb = read(f, as_version=4)
    validate(nb)
    assert isvalid(nb)


@pytest.mark.parametrize("validator_name", VALIDATORS)
def test_nb4_document_info(validator_name):
    """Test that a notebook with document_info passes validation"""
    set_validator(validator_name)
    with TestsBase.fopen("test4docinfo.ipynb", "r") as f:
        nb = read(f, as_version=4)
    validate(nb)
    assert isvalid(nb)


@pytest.mark.parametrize("validator_name", VALIDATORS)
def test_nb4custom(validator_name):
    """Test that a notebook with a custom JSON mimetype passes validation"""
    set_validator(validator_name)
    with TestsBase.fopen("test4custom.ipynb", "r") as f:
        nb = read(f, as_version=4)
    validate(nb)
    assert isvalid(nb)


@pytest.mark.parametrize("validator_name", VALIDATORS)
def test_nb4jupyter_metadata(validator_name):
    """Test that a notebook with a jupyter metadata passes validation"""
    set_validator(validator_name)
    with TestsBase.fopen("test4jupyter_metadata.ipynb", "r") as f:
        nb = read(f, as_version=4)
    validate(nb)
    assert isvalid(nb)


@pytest.mark.parametrize("validator_name", VALIDATORS)
def test_nb4jupyter_metadata_timings(validator_name):
    """Tests that a notebook with "timing" in metadata passes validation"""
    set_validator(validator_name)
    with TestsBase.fopen("test4jupyter_metadata_timings.ipynb", "r") as f:
        nb = read(f, as_version=4)
    validate(nb)
    assert isvalid(nb)


@pytest.mark.parametrize("validator_name", VALIDATORS)
def test_invalid(validator_name):
    """Test than an invalid notebook does not pass validation"""
    set_validator(validator_name)
    # this notebook has a few different errors:
    # - one cell is missing its source
    # - invalid cell type
    # - invalid output_type
    with TestsBase.fopen("invalid.ipynb", "r") as f:
        nb = read(f, as_version=4)
    with pytest.raises(ValidationError):
        validate(nb)
    assert not isvalid(nb)


@pytest.mark.parametrize("validator_name", VALIDATORS)
def test_validate_empty(validator_name):
    """Test that an empty notebook (invalid) fails validation"""
    set_validator(validator_name)
    with pytest.raises(ValidationError) as e:
        validate({})


@pytest.mark.parametrize("validator_name", VALIDATORS)
def test_future(validator_name):
    """Test that a notebook from the future with extra keys passes validation"""
    set_validator(validator_name)
    with TestsBase.fopen("test4plus.ipynb", "r") as f:
        nb = read(f, as_version=4)
    with pytest.raises(ValidationError):
        validate(nb, version=4, version_minor=3)

    assert not isvalid(nb, version=4, version_minor=3)
    assert isvalid(nb)


@pytest.mark.parametrize("validator_name", VALIDATORS)
def test_validation_error(validator_name):
    set_validator(validator_name)
    with TestsBase.fopen("invalid.ipynb", "r") as f:
        nb = read(f, as_version=4)
    with pytest.raises(ValidationError) as exception_info:
        validate(nb)

    s = str(exception_info.value)
    assert re.compile(r"validating .required. in markdown_cell").search(s)
    assert re.compile(r"source.* is a required property").search(s)
    assert re.compile(r"On instance\[u?['\"].*cells['\"]\]\[0\]").search(s)
    assert len(s.splitlines()) < 10


@pytest.mark.parametrize("validator_name", VALIDATORS)
def test_iter_validation_error(validator_name):
    set_validator(validator_name)
    with TestsBase.fopen("invalid.ipynb", "r") as f:
        nb = read(f, as_version=4)

    errors = list(iter_validate(nb))
    assert len(errors) == 3
    assert {e.ref for e in errors} == {"markdown_cell", "heading_cell", "bad stream"}


@pytest.mark.parametrize("validator_name", VALIDATORS)
def test_iter_validation_empty(validator_name):
    """Test that an empty notebook (invalid) fails validation via iter_validate"""
    set_validator(validator_name)
    errors = list(iter_validate({}))
    assert len(errors)
    assert type(errors[0]) == ValidationError


@pytest.mark.parametrize("validator_name", VALIDATORS)
def test_validation_no_version(validator_name):
    """Test that an invalid notebook with no version fails validation"""
    set_validator(validator_name)
    with pytest.raises(ValidationError) as e:
        validate({"invalid": "notebook"})


def test_invalid_validator_raises_value_error():
    """Test that an invalid notebook with no version fails validation"""
    set_validator("foobar")
    with pytest.raises(ValueError), TestsBase.fopen("test2.ipynb", "r") as f:
        nb = read(f, as_version=4)


def test_invalid_validator_raises_value_error_after_read():
    """Test that an invalid notebook with no version fails validation"""
    set_validator("jsonschema")
    with TestsBase.fopen("test2.ipynb", "r") as f:
        nb = read(f, as_version=4)

    set_validator("foobar")
    with pytest.raises(ValueError):
        validate(nb)


def test_fallback_validator_with_iter_errors_using_ref(recwarn):
    """
    Test that when creating a standalone object (code_cell etc)
    the default validator is used as fallback.
    """
    set_validator("fastjsonschema")
    nbformat.v4.new_code_cell()
    nbformat.v4.new_markdown_cell()
    nbformat.v4.new_raw_cell()
    assert len(recwarn) == 0


def test_non_unique_cell_ids():
    """Test than a non-unique cell id does not pass validation"""
    with TestsBase.fopen("invalid_unique_cell_id.ipynb", "r") as f:
        # Avoids validate call from `.read`
        nb = nbformat.from_dict(json.load(f))
    with pytest.raises(ValidationError), pytest.warns(DeprecationWarning):
        validate(nb, repair_duplicate_cell_ids=False)
    # try again to verify that we didn't modify the content
    with pytest.raises(ValidationError), pytest.warns(DeprecationWarning):
        validate(nb, repair_duplicate_cell_ids=False)


def test_repair_non_unique_cell_ids():
    """Test that we will repair non-unique cell ids if asked during validation"""

    with TestsBase.fopen("invalid_unique_cell_id.ipynb", "r") as f:
        # Avoids validate call from `.read`
        nb = nbformat.from_dict(json.load(f))
    with pytest.warns(DuplicateCellId):
        validate(nb)
    assert isvalid(nb)


@pytest.mark.filterwarnings("ignore::nbformat.warnings.MissingIDFieldWarning")
def test_no_cell_ids():
    """Test that a cell without a cell ID does not pass validation"""

    with TestsBase.fopen("v4_5_no_cell_id.ipynb", "r") as f:
        # Avoids validate call from `.read`
        nb = nbformat.from_dict(json.load(f))
    with pytest.raises(ValidationError), pytest.warns(DeprecationWarning):
        validate(nb, repair_duplicate_cell_ids=False)
    # try again to verify that we didn't modify the content
    with pytest.raises(ValidationError), pytest.warns(DeprecationWarning):
        validate(nb, repair_duplicate_cell_ids=False)


@pytest.mark.filterwarnings("ignore::nbformat.warnings.MissingIDFieldWarning")
def test_repair_no_cell_ids():
    """Test that we will repair cells without ids if asked during validation"""

    with TestsBase.fopen("v4_5_no_cell_id.ipynb", "r") as f:
        # Avoids validate call from `.read`
        nb = nbformat.from_dict(json.load(f))
    validate(nb)
    assert isvalid(nb)


def test_invalid_cell_id():
    """Test than an invalid cell id does not pass validation"""
    with TestsBase.fopen("invalid_cell_id.ipynb", "r") as f:
        nb = read(f, as_version=4)
    with pytest.raises(ValidationError):
        validate(nb)
    assert not isvalid(nb)


def test_notebook_invalid_without_min_version():
    with TestsBase.fopen("no_min_version.ipynb", "r") as f:
        nb = read(f, as_version=4)
    with pytest.raises(ValidationError):
        validate(nb)


def test_notebook_v3_valid_without_min_version():
    with TestsBase.fopen("test3_no_min_version.ipynb", "r") as f:
        nb = read(f, as_version=4)
    validate(nb)


def test_notebook_invalid_without_main_version():
    pass


def test_strip_invalid_metadata():
    with TestsBase.fopen("v4_5_invalid_metadata.ipynb", "r") as f:
        nb = nbformat.from_dict(json.load(f))
    assert not isvalid(nb)
    with pytest.warns(DeprecationWarning):
        validate(nb, strip_invalid_metadata=True)
    assert isvalid(nb)
nbformat-5.9.1/tests/v1/000077500000000000000000000000001445275403000150325ustar00rootroot00000000000000nbformat-5.9.1/tests/v1/__init__.py000066400000000000000000000000001445275403000171310ustar00rootroot00000000000000nbformat-5.9.1/tests/v1/nbexamples.py000066400000000000000000000005741445275403000175500ustar00rootroot00000000000000from nbformat.v1.nbbase import new_code_cell, new_notebook, new_text_cell

nb0 = new_notebook()

nb0.cells.append(new_text_cell(text="Some NumPy Examples"))


nb0.cells.append(new_code_cell(code="import numpy", prompt_number=1))

nb0.cells.append(new_code_cell(code="a = numpy.random.rand(100)", prompt_number=2))

nb0.cells.append(new_code_cell(code="print a", prompt_number=3))
nbformat-5.9.1/tests/v1/test_json.py000066400000000000000000000003431445275403000174140ustar00rootroot00000000000000from unittest import TestCase

from nbformat.v1.nbjson import reads, writes

from .nbexamples import nb0


class TestJSON(TestCase):
    def test_roundtrip(self):
        s = writes(nb0)
        self.assertEqual(reads(s), nb0)
nbformat-5.9.1/tests/v1/test_nbbase.py000066400000000000000000000021031445275403000176710ustar00rootroot00000000000000from unittest import TestCase

from nbformat.v1.nbbase import new_code_cell, new_notebook, new_text_cell


class TestCell(TestCase):
    def test_empty_code_cell(self):
        cc = new_code_cell()
        self.assertEqual(cc.cell_type, "code")
        self.assertEqual("code" not in cc, True)
        self.assertEqual("prompt_number" not in cc, True)

    def test_code_cell(self):
        cc = new_code_cell(code="a=10", prompt_number=0)
        self.assertEqual(cc.code, "a=10")
        self.assertEqual(cc.prompt_number, 0)

    def test_empty_text_cell(self):
        tc = new_text_cell()
        self.assertEqual(tc.cell_type, "text")
        self.assertEqual("text" not in tc, True)

    def test_text_cell(self):
        tc = new_text_cell("hi")
        self.assertEqual(tc.text, "hi")


class TestNotebook(TestCase):
    def test_empty_notebook(self):
        nb = new_notebook()
        self.assertEqual(nb.cells, [])

    def test_notebooke(self):
        cells = [new_code_cell(), new_text_cell()]
        nb = new_notebook(cells=cells)
        self.assertEqual(nb.cells, cells)
nbformat-5.9.1/tests/v2/000077500000000000000000000000001445275403000150335ustar00rootroot00000000000000nbformat-5.9.1/tests/v2/__init__.py000066400000000000000000000000001445275403000171320ustar00rootroot00000000000000nbformat-5.9.1/tests/v2/nbexamples.py000066400000000000000000000047771445275403000175620ustar00rootroot00000000000000import os
from base64 import encodebytes

from nbformat.v2.nbbase import (
    new_author,
    new_code_cell,
    new_metadata,
    new_notebook,
    new_output,
    new_text_cell,
    new_worksheet,
)

# some random base64-encoded *bytes*
png = encodebytes(os.urandom(5))
jpeg = encodebytes(os.urandom(6))

ws = new_worksheet(name="worksheet1")

ws.cells.append(new_text_cell("html", source="Some NumPy Examples", rendered="Some NumPy Examples"))


ws.cells.append(new_code_cell(input="import numpy", prompt_number=1, collapsed=False))

ws.cells.append(new_text_cell("markdown", source="A random array", rendered="A random array"))

ws.cells.append(new_code_cell(input="a = numpy.random.rand(100)", prompt_number=2, collapsed=True))

ws.cells.append(
    new_code_cell(
        input="print a",
        prompt_number=3,
        collapsed=False,
        outputs=[
            new_output(
                output_type="pyout",
                output_text="",
                output_html="The HTML rep",
                output_latex="$a$",
                output_png=png,
                output_jpeg=jpeg,
                output_svg="",
                output_json="json data",
                output_javascript="var i=0;",
                prompt_number=3,
            ),
            new_output(
                output_type="display_data",
                output_text="",
                output_html="The HTML rep",
                output_latex="$a$",
                output_png=png,
                output_jpeg=jpeg,
                output_svg="",
                output_json="json data",
                output_javascript="var i=0;",
            ),
            new_output(
                output_type="pyerr",
                etype="NameError",
                evalue="NameError was here",
                traceback=["frame 0", "frame 1", "frame 2"],
            ),
        ],
    )
)

authors = [
    new_author(
        name="Bart Simpson",
        email="bsimpson@fox.com",
        affiliation="Fox",
        url="http://www.fox.com",
    )
]
md = new_metadata(
    name="My Notebook",
    license="BSD",
    created="8601_goes_here",
    modified="8601_goes_here",
    gistid="21341231",
    authors=authors,
)

nb0 = new_notebook(worksheets=[ws, new_worksheet(name="worksheet2")], metadata=md)

nb0_py = """# -*- coding: utf-8 -*-
# 2

# 

# Some NumPy Examples

# 

import numpy

# 

# A random array

# 

a = numpy.random.rand(100)

# 

print a

"""
�nbformat-5.9.1/tests/v2/test_json.py����������������������������������������������������������������0000664�0000000�0000000�00000001706�14452754030�0017421�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from unittest import TestCase

from nbformat.v2.nbjson import reads, writes

from .nbexamples import nb0


class TestJSON(TestCase):
    def test_roundtrip(self):
        s = writes(nb0)
        #        print
        #        print pprint.pformat(nb0,indent=2)
        #        print
        #        print pprint.pformat(reads(s),indent=2)
        #        print
        #        print s
        self.assertEqual(reads(s), nb0)

    def test_roundtrip_nosplit(self):
        """Ensure that multiline blobs are still readable"""
        # ensures that notebooks written prior to splitlines change
        # are still readable.
        s = writes(nb0, split_lines=False)
        self.assertEqual(reads(s), nb0)

    def test_roundtrip_split(self):
        """Ensure that splitting multiline blocks is safe"""
        # This won't differ from test_roundtrip unless the default changes
        s = writes(nb0, split_lines=True)
        self.assertEqual(reads(s), nb0)
����������������������������������������������������������nbformat-5.9.1/tests/v2/test_nbbase.py��������������������������������������������������������������0000664�0000000�0000000�00000010344�14452754030�0017700�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from unittest import TestCase

from nbformat.v2.nbbase import (
    NotebookNode,
    new_author,
    new_code_cell,
    new_metadata,
    new_notebook,
    new_output,
    new_text_cell,
    new_worksheet,
)


class TestCell(TestCase):
    def test_empty_code_cell(self):
        cc = new_code_cell()
        self.assertEqual(cc.cell_type, "code")
        self.assertEqual("input" not in cc, True)
        self.assertEqual("prompt_number" not in cc, True)
        self.assertEqual(cc.outputs, [])
        self.assertEqual(cc.collapsed, False)

    def test_code_cell(self):
        cc = new_code_cell(input="a=10", prompt_number=0, collapsed=True)
        cc.outputs = [
            new_output(output_type="pyout", output_svg="foo", output_text="10", prompt_number=0)
        ]
        self.assertEqual(cc.input, "a=10")
        self.assertEqual(cc.prompt_number, 0)
        self.assertEqual(cc.language, "python")
        self.assertEqual(cc.outputs[0].svg, "foo")
        self.assertEqual(cc.outputs[0].text, "10")
        self.assertEqual(cc.outputs[0].prompt_number, 0)
        self.assertEqual(cc.collapsed, True)

    def test_pyerr(self):
        o = new_output(
            output_type="pyerr",
            etype="NameError",
            evalue="Name not found",
            traceback=["frame 0", "frame 1", "frame 2"],
        )
        self.assertEqual(o.output_type, "pyerr")
        self.assertEqual(o.etype, "NameError")
        self.assertEqual(o.evalue, "Name not found")
        self.assertEqual(o.traceback, ["frame 0", "frame 1", "frame 2"])

    def test_empty_html_cell(self):
        tc = new_text_cell("html")
        self.assertEqual(tc.cell_type, "html")
        self.assertEqual("source" not in tc, True)
        self.assertEqual("rendered" not in tc, True)

    def test_html_cell(self):
        tc = new_text_cell("html", "hi", "hi")
        self.assertEqual(tc.source, "hi")
        self.assertEqual(tc.rendered, "hi")

    def test_empty_markdown_cell(self):
        tc = new_text_cell("markdown")
        self.assertEqual(tc.cell_type, "markdown")
        self.assertEqual("source" not in tc, True)
        self.assertEqual("rendered" not in tc, True)

    def test_markdown_cell(self):
        tc = new_text_cell("markdown", "hi", "hi")
        self.assertEqual(tc.source, "hi")
        self.assertEqual(tc.rendered, "hi")


class TestWorksheet(TestCase):
    def test_empty_worksheet(self):
        ws = new_worksheet()
        self.assertEqual(ws.cells, [])
        self.assertEqual("name" not in ws, True)

    def test_worksheet(self):
        cells = [new_code_cell(), new_text_cell("html")]
        ws = new_worksheet(cells=cells, name="foo")
        self.assertEqual(ws.cells, cells)
        self.assertEqual(ws.name, "foo")


class TestNotebook(TestCase):
    def test_empty_notebook(self):
        nb = new_notebook()
        self.assertEqual(nb.worksheets, [])
        self.assertEqual(nb.metadata, NotebookNode())
        self.assertEqual(nb.nbformat, 2)

    def test_notebook(self):
        worksheets = [new_worksheet(), new_worksheet()]
        metadata = new_metadata(name="foo")
        nb = new_notebook(metadata=metadata, worksheets=worksheets)
        self.assertEqual(nb.metadata.name, "foo")
        self.assertEqual(nb.worksheets, worksheets)
        self.assertEqual(nb.nbformat, 2)


class TestMetadata(TestCase):
    def test_empty_metadata(self):
        md = new_metadata()
        self.assertEqual("name" not in md, True)
        self.assertEqual("authors" not in md, True)
        self.assertEqual("license" not in md, True)
        self.assertEqual("saved" not in md, True)
        self.assertEqual("modified" not in md, True)
        self.assertEqual("gistid" not in md, True)

    def test_metadata(self):
        authors = [new_author(name="Bart Simpson", email="bsimpson@fox.com")]
        md = new_metadata(
            name="foo",
            license="BSD",
            created="today",
            modified="now",
            gistid="21341231",
            authors=authors,
        )
        self.assertEqual(md.name, "foo")
        self.assertEqual(md.license, "BSD")
        self.assertEqual(md.created, "today")
        self.assertEqual(md.modified, "now")
        self.assertEqual(md.gistid, "21341231")
        self.assertEqual(md.authors, authors)
��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v2/test_nbpy.py����������������������������������������������������������������0000664�0000000�0000000�00000000330�14452754030�0017410�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from unittest import TestCase

from nbformat.v2.nbpy import writes

from .nbexamples import nb0, nb0_py


class TestPy(TestCase):
    def test_write(self):
        s = writes(nb0)
        self.assertEqual(s, nb0_py)
��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v3/����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�14452754030�0015034�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v3/__init__.py�����������������������������������������������������������������0000664�0000000�0000000�00000000000�14452754030�0017133�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v3/formattest.py���������������������������������������������������������������0000664�0000000�0000000�00000003025�14452754030�0017576�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import os
import shutil
import tempfile
from typing import Any, Optional

pjoin = os.path.join

from .nbexamples import nb0


def open_utf8(fname, mode):
    return open(fname, mode=mode, encoding="utf-8")  # noqa


class NBFormatTest:
    """Mixin for writing notebook format tests"""

    # override with appropriate values in subclasses
    nb0_ref: Optional[Any] = None
    ext: Optional[str] = None
    mod: Optional[Any] = None

    def setUp(self):
        self.wd = tempfile.mkdtemp()

    def tearDown(self):
        shutil.rmtree(self.wd)

    def assertNBEquals(self, nba, nbb):
        self.assertEqual(nba, nbb)  # type:ignore[attr-defined]

    def test_writes(self):
        assert self.mod is not None
        s = self.mod.writes(nb0)
        if self.nb0_ref:
            self.assertNBEquals(s, self.nb0_ref)

    def test_reads(self):
        assert self.mod is not None
        s = self.mod.writes(nb0)
        nb = self.mod.reads(s)

    def test_roundtrip(self):
        assert self.mod is not None
        s = self.mod.writes(nb0)
        self.assertNBEquals(self.mod.reads(s), nb0)

    def test_write_file(self):
        assert self.mod is not None
        with open_utf8(pjoin(self.wd, "nb0.%s" % self.ext), "w") as f:
            self.mod.write(nb0, f)

    def test_read_file(self):
        assert self.mod is not None
        with open_utf8(pjoin(self.wd, "nb0.%s" % self.ext), "w") as f:
            self.mod.write(nb0, f)

        with open_utf8(pjoin(self.wd, "nb0.%s" % self.ext), "r") as f:
            nb = self.mod.read(f)
�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v3/nbexamples.py���������������������������������������������������������������0000664�0000000�0000000�00000006411�14452754030�0017546�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import os
from base64 import encodebytes

from nbformat.v3.nbbase import (
    nbformat,
    nbformat_minor,
    new_author,
    new_code_cell,
    new_heading_cell,
    new_metadata,
    new_notebook,
    new_output,
    new_text_cell,
    new_worksheet,
)

# some random base64-encoded *text*
png = encodebytes(os.urandom(5)).decode("ascii")
jpeg = encodebytes(os.urandom(6)).decode("ascii")

ws = new_worksheet()

ws.cells.append(
    new_text_cell(
        "html",
        source="Some NumPy Examples",
    )
)


ws.cells.append(new_code_cell(input="import numpy", prompt_number=1, collapsed=False))

ws.cells.append(
    new_text_cell(
        "markdown",
        source="A random array",
    )
)

ws.cells.append(
    new_text_cell(
        "raw",
        source="A random array",
    )
)

ws.cells.append(new_heading_cell("My Heading", level=2))

ws.cells.append(new_code_cell(input="a = numpy.random.rand(100)", prompt_number=2, collapsed=True))
ws.cells.append(
    new_code_cell(
        input="a = 10\nb = 5\n",
        prompt_number=3,
    )
)
ws.cells.append(
    new_code_cell(
        input="a = 10\nb = 5",
        prompt_number=4,
    )
)

ws.cells.append(
    new_code_cell(
        input='print "ünîcødé"',
        prompt_number=3,
        collapsed=False,
        outputs=[
            new_output(
                output_type="pyout",
                output_text="",
                output_html="The HTML rep",
                output_latex="$a$",
                output_png=png,
                output_jpeg=jpeg,
                output_svg="",
                output_json='{"json": "data"}',
                output_javascript="var i=0;",
                prompt_number=3,
            ),
            new_output(
                output_type="display_data",
                output_text="",
                output_html="The HTML rep",
                output_latex="$a$",
                output_png=png,
                output_jpeg=jpeg,
                output_svg="",
                output_json='{"json": "data"}',
                output_javascript="var i=0;",
            ),
            new_output(
                output_type="pyerr",
                ename="NameError",
                evalue="NameError was here",
                traceback=["frame 0", "frame 1", "frame 2"],
            ),
            new_output(output_type="stream", output_text="foo\rbar\r\n"),
            new_output(output_type="stream", stream="stderr", output_text="\rfoo\rbar\n"),
        ],
    )
)

authors = [
    new_author(
        name="Bart Simpson",
        email="bsimpson@fox.com",
        affiliation="Fox",
        url="http://www.fox.com",
    )
]
md = new_metadata(
    name="My Notebook",
    license="BSD",
    created="8601_goes_here",
    modified="8601_goes_here",
    gistid="21341231",
    authors=authors,
)

nb0 = new_notebook(worksheets=[ws, new_worksheet()], metadata=md)

nb0_py = """# -*- coding: utf-8 -*-
# %i.%i

# 

# Some NumPy Examples

# 

import numpy

# 

# A random array

# 

# A random array

# 

# My Heading

# 

a = numpy.random.rand(100)

# 

a = 10
b = 5

# 

a = 10
b = 5

# 

print "ünîcødé"

""" % (
    nbformat,
    nbformat_minor,
)
�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v3/test_json.py����������������������������������������������������������������0000664�0000000�0000000�00000006443�14452754030�0017425�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import copy
import json
from base64 import decodebytes
from unittest import TestCase

from nbformat.v3 import nbjson
from nbformat.v3.nbbase import from_dict
from nbformat.v3.nbjson import writes

from . import formattest
from .nbexamples import nb0


class TestJSON(formattest.NBFormatTest, TestCase):
    nb0_ref = None
    ext = "ipynb"
    mod = nbjson

    def test_roundtrip_nosplit(self):
        """Ensure that multiline blobs are still readable"""
        # ensures that notebooks written prior to splitlines change
        # are still readable.
        s = writes(nb0, split_lines=False)
        self.assertEqual(nbjson.reads(s), nb0)

    def test_roundtrip_split(self):
        """Ensure that splitting multiline blocks is safe"""
        # This won't differ from test_roundtrip unless the default changes
        s = writes(nb0, split_lines=True)
        self.assertEqual(nbjson.reads(s), nb0)

    def test_strip_transient(self):
        """transient values aren't written to files"""
        nb = copy.deepcopy(nb0)
        nb.orig_nbformat = 2
        nb.orig_nbformat_minor = 3
        nb.worksheets[0].cells[0].metadata.trusted = False
        nbs = nbjson.writes(nb)

        nb2 = from_dict(json.loads(nbs))
        self.assertNotIn("orig_nbformat", nb2)
        self.assertNotIn("orig_nbformat_minor", nb2)
        for cell in nb2.worksheets[0].cells:
            self.assertNotIn("trusted", cell.metadata)

    def test_to_json(self):
        """to_notebook_json doesn't strip transient"""
        nb = copy.deepcopy(nb0)
        nb.orig_nbformat = 2
        nb.orig_nbformat_minor = 3
        nb.worksheets[0].cells[0].metadata.trusted = False
        nbs = json.dumps(nb)
        nb2 = nbjson.to_notebook(json.loads(nbs))

        nb2 = from_dict(json.loads(nbs))
        self.assertIn("orig_nbformat", nb2)
        self.assertIn("orig_nbformat_minor", nb2)
        cell = nb2.worksheets[0].cells[0]
        self.assertIn("trusted", cell.metadata)

    def test_read_png(self):
        """PNG output data is b64 unicode"""
        s = writes(nb0)
        nb1 = nbjson.reads(s)
        found_png = False
        for cell in nb1.worksheets[0].cells:
            if "outputs" not in cell:
                continue
            for output in cell.outputs:
                if "png" in output:
                    found_png = True
                    pngdata = output["png"]
                    self.assertEqual(type(pngdata), str)
                    # test that it is valid b64 data
                    b64bytes = pngdata.encode("ascii")
                    raw_bytes = decodebytes(b64bytes)
        assert found_png, "never found png output"

    def test_read_jpeg(self):
        """JPEG output data is b64 unicode"""
        s = writes(nb0)
        nb1 = nbjson.reads(s)
        found_jpeg = False
        for cell in nb1.worksheets[0].cells:
            if "outputs" not in cell:
                continue
            for output in cell.outputs:
                if "jpeg" in output:
                    found_jpeg = True
                    jpegdata = output["jpeg"]
                    self.assertEqual(type(jpegdata), str)
                    # test that it is valid b64 data
                    b64bytes = jpegdata.encode("ascii")
                    raw_bytes = decodebytes(b64bytes)
        assert found_jpeg, "never found jpeg output"
�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v3/test_misc.py����������������������������������������������������������������0000664�0000000�0000000�00000002103�14452754030�0017374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import os
from unittest import TestCase

from nbformat.v3 import parse_filename


class MiscTests(TestCase):
    def check_filename(self, path, exp_fname, exp_bname, exp_format):
        fname, bname, fmt = parse_filename(path)
        self.assertEqual(fname, exp_fname)
        self.assertEqual(bname, exp_bname)
        self.assertEqual(fmt, exp_format)

    def test_parse_filename(self):
        # check format detection
        self.check_filename("test.ipynb", "test.ipynb", "test", "json")
        self.check_filename("test.json", "test.json", "test", "json")
        self.check_filename("test.py", "test.py", "test", "py")

        # check parsing an unknown format
        self.check_filename("test.nb", "test.nb.ipynb", "test.nb", "json")

        # check parsing a full file path
        abs_path = os.path.abspath("test.ipynb")
        basename, ext = os.path.splitext(abs_path)
        self.check_filename(abs_path, abs_path, basename, "json")

        # check parsing a file name containing dots
        self.check_filename("test.nb.ipynb", "test.nb.ipynb", "test.nb", "json")
�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v3/test_nbbase.py��������������������������������������������������������������0000664�0000000�0000000�00000013565�14452754030�0017711�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from unittest import TestCase

import pytest

from nbformat.v3.nbbase import (
    NotebookNode,
    nbformat,
    new_author,
    new_code_cell,
    new_heading_cell,
    new_metadata,
    new_notebook,
    new_output,
    new_text_cell,
    new_worksheet,
)


class TestCell(TestCase):
    def test_empty_code_cell(self):
        cc = new_code_cell()
        self.assertEqual(cc.cell_type, "code")
        self.assertEqual("input" not in cc, True)
        self.assertEqual("prompt_number" not in cc, True)
        self.assertEqual(cc.outputs, [])
        self.assertEqual(cc.collapsed, False)

    def test_code_cell(self):
        cc = new_code_cell(input="a=10", prompt_number=0, collapsed=True)
        cc.outputs = [
            new_output(output_type="pyout", output_svg="foo", output_text="10", prompt_number=0)
        ]
        self.assertEqual(cc.input, "a=10")
        self.assertEqual(cc.prompt_number, 0)
        self.assertEqual(cc.language, "python")
        self.assertEqual(cc.outputs[0].svg, "foo")
        self.assertEqual(cc.outputs[0].text, "10")
        self.assertEqual(cc.outputs[0].prompt_number, 0)
        self.assertEqual(cc.collapsed, True)

    def test_pyerr(self):
        o = new_output(
            output_type="pyerr",
            ename="NameError",
            evalue="Name not found",
            traceback=["frame 0", "frame 1", "frame 2"],
        )
        self.assertEqual(o.output_type, "pyerr")
        self.assertEqual(o.ename, "NameError")
        self.assertEqual(o.evalue, "Name not found")
        self.assertEqual(o.traceback, ["frame 0", "frame 1", "frame 2"])

    def test_empty_html_cell(self):
        tc = new_text_cell("html")
        self.assertEqual(tc.cell_type, "html")
        self.assertEqual("source" not in tc, True)

    def test_html_cell(self):
        tc = new_text_cell("html", "hi")
        self.assertEqual(tc.source, "hi")

    def test_empty_markdown_cell(self):
        tc = new_text_cell("markdown")
        self.assertEqual(tc.cell_type, "markdown")
        self.assertEqual("source" not in tc, True)

    def test_markdown_cell(self):
        tc = new_text_cell("markdown", "hi")
        self.assertEqual(tc.source, "hi")

    def test_empty_raw_cell(self):
        tc = new_text_cell("raw")
        self.assertEqual(tc.cell_type, "raw")
        self.assertEqual("source" not in tc, True)

    def test_raw_cell(self):
        tc = new_text_cell("raw", "hi")
        self.assertEqual(tc.source, "hi")

    def test_empty_heading_cell(self):
        tc = new_heading_cell()
        self.assertEqual(tc.cell_type, "heading")
        self.assertEqual("source" not in tc, True)

    def test_heading_cell(self):
        tc = new_heading_cell("hi", level=2)
        self.assertEqual(tc.source, "hi")
        self.assertEqual(tc.level, 2)


class TestWorksheet(TestCase):
    def test_empty_worksheet(self):
        ws = new_worksheet()
        self.assertEqual(ws.cells, [])
        self.assertEqual("name" not in ws, True)

    def test_worksheet(self):
        cells = [new_code_cell(), new_text_cell("html")]
        ws = new_worksheet(cells=cells)
        self.assertEqual(ws.cells, cells)


class TestNotebook(TestCase):
    def test_empty_notebook(self):
        nb = new_notebook()
        self.assertEqual(nb.worksheets, [])
        self.assertEqual(nb.metadata, NotebookNode())
        self.assertEqual(nb.nbformat, nbformat)

    def test_notebook(self):
        worksheets = [new_worksheet(), new_worksheet()]
        metadata = new_metadata(name="foo")
        nb = new_notebook(metadata=metadata, worksheets=worksheets)
        self.assertEqual(nb.metadata.name, "foo")
        self.assertEqual(nb.worksheets, worksheets)
        self.assertEqual(nb.nbformat, nbformat)

    def test_notebook_name(self):
        worksheets = [new_worksheet(), new_worksheet()]
        nb = new_notebook(name="foo", worksheets=worksheets)
        self.assertEqual(nb.metadata.name, "foo")
        self.assertEqual(nb.worksheets, worksheets)
        self.assertEqual(nb.nbformat, nbformat)


class TestMetadata(TestCase):
    def test_empty_metadata(self):
        md = new_metadata()
        self.assertEqual("name" not in md, True)
        self.assertEqual("authors" not in md, True)
        self.assertEqual("license" not in md, True)
        self.assertEqual("saved" not in md, True)
        self.assertEqual("modified" not in md, True)
        self.assertEqual("gistid" not in md, True)

    def test_metadata(self):
        authors = [new_author(name="Bart Simpson", email="bsimpson@fox.com")]
        md = new_metadata(
            name="foo",
            license="BSD",
            created="today",
            modified="now",
            gistid="21341231",
            authors=authors,
        )
        self.assertEqual(md.name, "foo")
        self.assertEqual(md.license, "BSD")
        self.assertEqual(md.created, "today")
        self.assertEqual(md.modified, "now")
        self.assertEqual(md.gistid, "21341231")
        self.assertEqual(md.authors, authors)


class TestOutputs(TestCase):
    def test_binary_png(self):
        with pytest.warns(UserWarning, match="bytes instead of likely base64"):
            out = new_output(output_png=b"\x89PNG\r\n\x1a\n", output_type="display_data")

    def test_b64b6tes_png(self):
        # really those tests are wrong, this is not b64, if prefixed by b
        with pytest.warns(UserWarning, match="bytes instead of likely base64"):
            out = new_output(output_png=b"iVBORw0KG", output_type="display_data")

    def test_binary_jpeg(self):
        with pytest.warns(UserWarning, match="bytes instead of likely base64"):
            out = new_output(output_jpeg=b"\xff\xd8", output_type="display_data")

    def test_b64b6tes_jpeg(self):
        # really those tests are wrong, this is not b64, if prefixed by b
        with pytest.warns(UserWarning, match="bytes instead of likely base64"):
            out = new_output(output_jpeg=b"/9", output_type="display_data")
�������������������������������������������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v3/test_nbpy.py����������������������������������������������������������������0000664�0000000�0000000�00000002557�14452754030�0017426�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from unittest import TestCase

from nbformat.v3 import nbpy

from . import formattest
from .nbexamples import nb0_py


class TestPy(formattest.NBFormatTest, TestCase):
    nb0_ref = nb0_py
    ext = "py"
    mod = nbpy
    ignored_keys = ["collapsed", "outputs", "prompt_number", "metadata"]  # noqa

    def assertSubset(self, da, db):
        """assert that da is a subset of db, ignoring self.ignored_keys.

        Called recursively on containers, ultimately comparing individual
        elements.
        """
        if isinstance(da, dict):
            for k, v in da.items():
                if k in self.ignored_keys:
                    continue
                self.assertTrue(k in db)
                self.assertSubset(v, db[k])
        elif isinstance(da, list):
            for a, b in zip(da, db):
                self.assertSubset(a, b)
        else:
            if isinstance(da, str) and isinstance(db, str):
                # pyfile is not sensitive to preserving leading/trailing
                # newlines in blocks through roundtrip
                da = da.strip("\n")
                db = db.strip("\n")
            self.assertEqual(da, db)
        return True

    def assertNBEquals(self, nba, nbb):
        # since roundtrip is lossy, only compare keys that are preserved
        # assumes nba is read from my file format
        return self.assertSubset(nba, nbb)
�������������������������������������������������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v4/����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�14452754030�0015035�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v4/__init__.py�����������������������������������������������������������������0000664�0000000�0000000�00000000000�14452754030�0017134�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v4/formattest.py���������������������������������������������������������������0000664�0000000�0000000�00000003025�14452754030�0017577�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import os
import shutil
import tempfile
from typing import Any, Optional

pjoin = os.path.join

from .nbexamples import nb0


def open_utf8(fname, mode):
    return open(fname, mode=mode, encoding="utf-8")  # noqa


class NBFormatTest:
    """Mixin for writing notebook format tests"""

    # override with appropriate values in subclasses
    nb0_ref: Optional[Any] = None
    ext: Optional[str] = None
    mod: Optional[Any] = None

    def setUp(self):
        self.wd = tempfile.mkdtemp()

    def tearDown(self):
        shutil.rmtree(self.wd)

    def assertNBEquals(self, nba, nbb):
        self.assertEqual(nba, nbb)  # type:ignore[attr-defined]

    def test_writes(self):
        assert self.mod is not None
        s = self.mod.writes(nb0)
        if self.nb0_ref:
            self.assertNBEquals(s, self.nb0_ref)

    def test_reads(self):
        assert self.mod is not None
        s = self.mod.writes(nb0)
        nb = self.mod.reads(s)

    def test_roundtrip(self):
        assert self.mod is not None
        s = self.mod.writes(nb0)
        self.assertNBEquals(self.mod.reads(s), nb0)

    def test_write_file(self):
        assert self.mod is not None
        with open_utf8(pjoin(self.wd, "nb0.%s" % self.ext), "w") as f:
            self.mod.write(nb0, f)

    def test_read_file(self):
        assert self.mod is not None
        with open_utf8(pjoin(self.wd, "nb0.%s" % self.ext), "w") as f:
            self.mod.write(nb0, f)

        with open_utf8(pjoin(self.wd, "nb0.%s" % self.ext), "r") as f:
            nb = self.mod.read(f)
�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v4/nbexamples.py���������������������������������������������������������������0000664�0000000�0000000�00000007205�14452754030�0017551�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import os
from base64 import encodebytes

from nbformat.v4.nbbase import (
    new_code_cell,
    new_markdown_cell,
    new_notebook,
    new_output,
    new_raw_cell,
)

# some random base64-encoded *text*
png = encodebytes(os.urandom(5)).decode("ascii")
jpeg = encodebytes(os.urandom(6)).decode("ascii")

cells = []
cells.append(
    new_markdown_cell(
        source="Some NumPy Examples",
    )
)


cells.append(
    new_code_cell(
        source="import numpy",
        execution_count=1,
    )
)

cells.append(
    new_markdown_cell(
        source="Cell with attachments",
        attachments={
            "attachment1": {
                "text/plain": "\n".join(["a", "b", "c"]),
                "application/vnd.stuff+json": ["a", 1, "x"],
            }
        },
    )
)

cells.append(
    new_raw_cell(
        source="A random array",
    )
)

cells.append(
    new_markdown_cell(
        source="## My Heading",
    )
)

cells.append(
    new_code_cell(
        source="a = numpy.random.rand(100)",
        execution_count=2,
    )
)
cells.append(
    new_code_cell(
        source="a = 10\nb = 5\n",
        execution_count=3,
    )
)
cells.append(
    new_code_cell(
        source="a = 10\nb = 5",
        execution_count=4,
    )
)

cells.append(
    new_code_cell(
        source="json_outputs()",
        execution_count=12,
        outputs=[
            new_output(
                output_type="display_data",
                data={
                    "text/plain": "",
                    "application/json": {"key": "value", "x": 5, "lis": [1, 2, "x"]},
                    "application/vnd.listofstr+json": ["a", "b", "c"],
                    "application/vnd.numbers+json": [1, 2, 3],
                    "application/vnd.number+json": 42,
                    "application/vnd.object+json": {
                        "number": 5,
                        "array": [1, 2],
                        "str": "x",
                    },
                    "application/vnd.string+json": "ok",
                },
            )
        ],
    )
)

cells.append(
    new_code_cell(
        source='print "ünîcødé"',
        execution_count=3,
        outputs=[
            new_output(
                output_type="execute_result",
                data={
                    "text/plain": "",
                    "text/html": "The HTML rep",
                    "text/latex": "$a$",
                    "image/png": png,
                    "image/jpeg": jpeg,
                    "image/svg+xml": "",
                    "application/json": {"key": "value"},
                    "application/javascript": "var i=0;",
                },
                execution_count=3,
            ),
            new_output(
                output_type="display_data",
                data={
                    "text/plain": "",
                    "text/html": "The HTML rep",
                    "text/latex": "$a$",
                    "image/png": png,
                    "image/jpeg": jpeg,
                    "image/svg+xml": "",
                    "application/json": {"key": "value"},
                    "application/javascript": "var i=0;",
                },
            ),
            new_output(
                output_type="error",
                ename="NameError",
                evalue="NameError was here",
                traceback=["frame 0", "frame 1", "frame 2"],
            ),
            new_output(output_type="stream", text="foo\rbar\r\n"),
            new_output(output_type="stream", name="stderr", text="\rfoo\rbar\n"),
        ],
    )
)

nb0 = new_notebook(
    cells=cells,
    metadata={
        "language": "python",
    },
)
�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v4/test_convert.py�������������������������������������������������������������0000664�0000000�0000000�00000005552�14452754030�0020135�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import copy
import os
from unittest import mock

import pytest

from nbformat import ValidationError, v3, v4, validate
from nbformat.v4 import convert
from nbformat.v4.nbjson import reads

from ..v3 import nbexamples as v3examples  # noqa
from . import nbexamples


def test_upgrade_notebook():
    nb03 = copy.deepcopy(v3examples.nb0)
    validate(nb03)
    nb04 = convert.upgrade(nb03)
    validate(nb04)


def test_downgrade_notebook():
    nb04 = copy.deepcopy(nbexamples.nb0)
    validate(nb04)
    nb03 = convert.downgrade(nb04)
    validate(nb03)


def test_upgrade_heading():
    # Fake the uuid generation for ids
    cell_ids = ["cell-1", "cell-2", "cell-3"]
    with mock.patch("nbformat.v4.convert.random_cell_id", side_effect=cell_ids), mock.patch(
        "nbformat.v4.nbbase.random_cell_id", side_effect=cell_ids
    ):
        v3h = v3.new_heading_cell
        v4m = v4.new_markdown_cell
        for v3cell, expected in [
            (
                v3h(source="foo", level=1),
                v4m(source="# foo"),
            ),
            (
                v3h(source="foo\nbar\nmulti-line\n", level=4),
                v4m(source="#### foo bar multi-line"),
            ),
            (
                v3h(source="ünìcö∂e–cønvërsioñ", level=4),
                v4m(source="#### ünìcö∂e–cønvërsioñ"),
            ),
        ]:
            upgraded = convert.upgrade_cell(v3cell)
            assert upgraded == expected


def test_downgrade_heading():
    v3h = v3.new_heading_cell
    v4m = v4.new_markdown_cell
    v3m = lambda source: v3.new_text_cell("markdown", source)  # noqa
    for v4cell, expected in [
        (
            v4m(source="# foo"),
            v3h(source="foo", level=1),
        ),
        (
            v4m(source="#foo"),
            v3h(source="foo", level=1),
        ),
        (
            v4m(source="#\tfoo"),
            v3h(source="foo", level=1),
        ),
        (
            v4m(source="# \t  foo"),
            v3h(source="foo", level=1),
        ),
        (
            v4m(source="# foo\nbar"),
            v3m(source="# foo\nbar"),
        ),
    ]:
        downgraded = convert.downgrade_cell(v4cell)
        assert downgraded == expected


def test_upgrade_v4_to_4_dot_5():
    here = os.path.dirname(__file__)
    with open(os.path.join(here, os.pardir, "test4.ipynb"), encoding="utf-8") as f:
        nb = reads(f.read())

    assert nb["nbformat_minor"] == 0
    validate(nb)
    assert nb.cells[0].get("id") is None

    nb_up = convert.upgrade(nb)
    assert nb_up["nbformat_minor"] == 5
    validate(nb_up)
    assert nb_up.cells[0]["id"] is not None


def test_upgrade_without_nbminor_version():
    here = os.path.dirname(__file__)
    with open(os.path.join(here, os.pardir, "no_min_version.ipynb"), encoding="utf-8") as f:
        nb = reads(f.read())

    with pytest.raises(ValidationError):
        convert.upgrade(nb)
������������������������������������������������������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v4/test_json.py����������������������������������������������������������������0000664�0000000�0000000�00000011721�14452754030�0017421�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import json
import os
import sys
from base64 import decodebytes
from unittest import TestCase

from nbformat.v4 import nbformat, nbformat_minor, nbjson
from nbformat.v4.nbjson import writes

from . import formattest
from .nbexamples import nb0

BASE_PATH = os.path.join(sys.modules["nbformat"].__path__[0], "v4")


class TestJSON(formattest.NBFormatTest, TestCase):
    nb0_ref = None
    ext = "ipynb"
    mod = nbjson

    def test_roundtrip_nosplit(self):
        """Ensure that multiline blobs are still readable"""
        # ensures that notebooks written prior to splitlines change
        # are still readable.
        s = writes(nb0, split_lines=False)
        self.assertEqual(nbjson.reads(s), nb0)

    def test_roundtrip_split(self):
        """Ensure that splitting multiline blocks is safe"""
        # This won't differ from test_roundtrip unless the default changes
        s = writes(nb0, split_lines=True)
        self.assertEqual(nbjson.reads(s), nb0)

    def test_splitlines(self):
        """Test splitlines in mime-bundles"""
        s = writes(nb0, split_lines=True)
        raw_nb = json.loads(s)

        for i, ref_cell in enumerate(nb0.cells):
            if ref_cell.source.strip() == "Cell with attachments":
                attach_ref = ref_cell["attachments"]["attachment1"]
                attach_json = raw_nb["cells"][i]["attachments"]["attachment1"]
            if ref_cell.source.strip() == "json_outputs()":
                output_ref = ref_cell["outputs"][0]["data"]
                output_json = raw_nb["cells"][i]["outputs"][0]["data"]

        for key, json_value in attach_json.items():
            if key == "text/plain":
                # text should be split
                assert json_value == attach_ref["text/plain"].splitlines(True)
            else:
                # JSON attachments
                assert json_value == attach_ref[key]

        # check that JSON outputs are left alone:
        for key, json_value in output_json.items():
            if key == "text/plain":
                # text should be split
                assert json_value == output_ref["text/plain"].splitlines(True)
            else:
                # JSON outputs should be left alone
                assert json_value == output_ref[key]

    def test_read_png(self):
        """PNG output data is b64 unicode"""
        s = writes(nb0)
        nb1 = nbjson.reads(s)
        found_png = False
        for cell in nb1.cells:
            if "outputs" not in cell:
                continue
            for output in cell.outputs:
                if "data" not in output:
                    continue
                if "image/png" in output.data:
                    found_png = True
                    pngdata = output.data["image/png"]
                    self.assertEqual(type(pngdata), str)
                    # test that it is valid b64 data
                    b64bytes = pngdata.encode("ascii")
                    raw_bytes = decodebytes(b64bytes)
        assert found_png, "never found png output"

    def test_read_jpeg(self):
        """JPEG output data is b64 unicode"""
        s = writes(nb0)
        nb1 = nbjson.reads(s)
        found_jpeg = False
        for cell in nb1.cells:
            if "outputs" not in cell:
                continue
            for output in cell.outputs:
                if "data" not in output:
                    continue
                if "image/jpeg" in output.data:
                    found_jpeg = True
                    jpegdata = output.data["image/jpeg"]
                    self.assertEqual(type(jpegdata), str)
                    # test that it is valid b64 data
                    b64bytes = jpegdata.encode("ascii")
                    raw_bytes = decodebytes(b64bytes)
        assert found_jpeg, "never found jpeg output"

    def test_latest_schema_matches(self):
        """Test to ensure all schema is locked to a known version"""
        assert nbformat == 4
        assert nbformat_minor == 5

    def test_base_version_matches_latest(self):
        """Test to ensure latest version file matches latest verison"""
        with open(os.path.join(BASE_PATH, "nbformat.v4.schema.json")) as schema_file:
            latest_schema = json.load(schema_file)
            with open(
                os.path.join(
                    BASE_PATH,
                    "nbformat.v{major}.{minor}.schema.json".format(
                        major=nbformat, minor=nbformat_minor
                    ),
                ),
            ) as schema_file:  # noqa
                ver_schema = json.load(schema_file)
            assert latest_schema == ver_schema

    def test_latest_matches_nbformat(self):
        """Test to ensure that the nbformat version matches the description of the latest schema"""
        with open(os.path.join(BASE_PATH, "nbformat.v4.schema.json")) as schema_file:
            schema = json.load(schema_file)
        assert schema["description"] == "Jupyter Notebook v{major}.{minor} JSON schema.".format(
            major=nbformat, minor=nbformat_minor
        )
�����������������������������������������������nbformat-5.9.1/tests/v4/test_nbbase.py��������������������������������������������������������������0000664�0000000�0000000�00000005720�14452754030�0017704�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Tests for the Python API for composing notebook elements"""

from nbformat.v4.nbbase import (
    NotebookNode,
    nbformat,
    new_code_cell,
    new_markdown_cell,
    new_notebook,
    new_output,
    new_raw_cell,
)


def test_empty_notebook():
    nb = new_notebook()
    assert nb.cells == []
    assert nb.metadata == NotebookNode()
    assert nb.nbformat == nbformat


def test_empty_markdown_cell():
    cell = new_markdown_cell()
    assert cell.cell_type == "markdown"
    assert cell.source == ""


def test_markdown_cell():
    cell = new_markdown_cell("* Søme markdown")
    assert cell.source == "* Søme markdown"


def test_empty_raw_cell():
    cell = new_raw_cell()
    assert cell.cell_type == "raw"
    assert cell.source == ""


def test_raw_cell():
    cell = new_raw_cell("hi")
    assert cell.source == "hi"


def test_empty_code_cell():
    cell = new_code_cell("hi")
    assert cell.cell_type == "code"
    assert cell.source == "hi"


def test_empty_display_data():
    output = new_output("display_data")
    assert output.output_type == "display_data"


def test_empty_stream():
    output = new_output("stream")
    assert output.output_type == "stream"
    assert output.name == "stdout"
    assert output.text == ""


def test_empty_execute_result():
    output = new_output("execute_result", execution_count=1)
    assert output.output_type == "execute_result"


mimebundle = {
    "text/plain": "some text",
    "application/json": {"key": "value"},
    "image/svg+xml": "ABCDEF",
    "application/octet-stream": "ABC-123",
    "application/vnd.foo+bar": "Some other stuff",
}


def test_display_data():
    output = new_output("display_data", mimebundle)
    for key, expected in mimebundle.items():
        assert output.data[key] == expected


def test_execute_result():
    output = new_output("execute_result", mimebundle, execution_count=10)
    assert output.execution_count == 10
    for key, expected in mimebundle.items():
        assert output.data[key] == expected


def test_error():
    o = new_output(
        output_type="error",
        ename="NameError",
        evalue="Name not found",
        traceback=["frame 0", "frame 1", "frame 2"],
    )
    assert o.output_type == "error"
    assert o.ename == "NameError"
    assert o.evalue == "Name not found"
    assert o.traceback == ["frame 0", "frame 1", "frame 2"]


def test_code_cell_with_outputs():
    cell = new_code_cell(
        execution_count=10,
        outputs=[
            new_output("display_data", mimebundle),
            new_output("stream", text="hello"),
            new_output("execute_result", mimebundle, execution_count=10),
        ],
    )
    assert cell.execution_count == 10
    assert len(cell.outputs) == 3
    er = cell.outputs[-1]
    assert er.execution_count == 10
    assert er["output_type"] == "execute_result"


def test_stream():
    output = new_output("stream", name="stderr", text="hello there")
    assert output.name == "stderr"
    assert output.text == "hello there"
������������������������������������������������nbformat-5.9.1/tests/v4/test_validate.py������������������������������������������������������������0000664�0000000�0000000�00000004625�14452754030�0020246�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Tests for nbformat validation"""

# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

import os

import pytest

from nbformat.v4.nbbase import nbformat, new_code_cell, new_markdown_cell, new_raw_cell
from nbformat.v4.nbjson import reads
from nbformat.validator import ValidationError, validate


def validate4(obj, ref=None):
    return validate(obj, ref, version=nbformat)


def test_valid_code_cell():
    cell = new_code_cell()
    validate4(cell, "code_cell")


def test_invalid_code_cell():
    cell = new_code_cell()

    cell["source"] = 5
    with pytest.raises(ValidationError):
        validate4(cell, "code_cell")

    cell = new_code_cell()
    del cell["metadata"]

    with pytest.raises(ValidationError):
        validate4(cell, "code_cell")

    cell = new_code_cell()
    del cell["source"]

    with pytest.raises(ValidationError):
        validate4(cell, "code_cell")

    cell = new_code_cell()
    del cell["cell_type"]

    with pytest.raises(ValidationError):
        validate4(cell, "code_cell")


def test_invalid_markdown_cell():
    cell = new_markdown_cell()

    cell["source"] = 5
    with pytest.raises(ValidationError):
        validate4(cell, "markdown_cell")

    cell = new_markdown_cell()
    del cell["metadata"]

    with pytest.raises(ValidationError):
        validate4(cell, "markdown_cell")

    cell = new_markdown_cell()
    del cell["source"]

    with pytest.raises(ValidationError):
        validate4(cell, "markdown_cell")

    cell = new_markdown_cell()
    del cell["cell_type"]

    with pytest.raises(ValidationError):
        validate4(cell, "markdown_cell")


def test_invalid_raw_cell():
    cell = new_raw_cell()

    cell["source"] = 5
    with pytest.raises(ValidationError):
        validate4(cell, "raw_cell")

    cell = new_raw_cell()
    del cell["metadata"]

    with pytest.raises(ValidationError):
        validate4(cell, "raw_cell")

    cell = new_raw_cell()
    del cell["source"]

    with pytest.raises(ValidationError):
        validate4(cell, "raw_cell")

    cell = new_raw_cell()
    del cell["cell_type"]

    with pytest.raises(ValidationError):
        validate4(cell, "raw_cell")


def test_sample_notebook():
    here = os.path.dirname(__file__)
    with open(
        os.path.join(here, os.pardir, os.pardir, "tests", "test4.ipynb"),
        encoding="utf-8",
    ) as f:
        nb = reads(f.read())
    validate4(nb)
�����������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v4_5_invalid_metadata.ipynb����������������������������������������������������0000664�0000000�0000000�00000002570�14452754030�0021676�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������{
 "cells": [
  {
   "id": "asdf",
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": "BAD: should be bool",
    "scrolled": "BAD: should be bool",
    "deletable": "BAD: should be bool",
    "editable": "BAD: should be bool",
    "format": "BAD: should be bool",
    "name": 12345,
    "tags": "BAD: should be list of str",
    "jupyter": "BAD: should be dict",
    "execution": "BAD: should be dict"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'bar'"
      ]
     },
     "execution_count": 1,
     "metadata": {
      "isolated": "BAD: should be bool"
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"foo\""
   ]
  },
  {
   "id": "jlkj",
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "source_hidden": "BAD: should be dict",
     "outputs_hidden": "BAD: should be dict"
    },
    "execution": {
     "iopub.execute_input": "BAD: should be ISO 8601 format",
     "iopub.status.busy": "BAD: should be ISO 8601 format",
     "shell.execute_reply": "BAD: should be ISO 8601 format",
     "iopub.status.idle": "BAD: should be ISO 8601 format"
    }
   },
   "outputs": [],
   "source": [
    "\"foo 2\""
   ]
  }
 ],
 "metadata": {
  "kernelspec": "BAD: should be a dict",
  "authors": "BAD: should be a list of dicts"
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
����������������������������������������������������������������������������������������������������������������������������������������nbformat-5.9.1/tests/v4_5_no_cell_id.ipynb����������������������������������������������������������0000664�0000000�0000000�00000001075�14452754030�0020476�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"foo\""
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������