pax_global_header00006660000000000000000000000064145741041700014515gustar00rootroot0000000000000052 comment=5f2c65271b48dc95fc75a9585cb1d6db0bb55557 jupyter_kernel_test-0.7.0/000077500000000000000000000000001457410417000156225ustar00rootroot00000000000000jupyter_kernel_test-0.7.0/.git-blame-ignore-revs000066400000000000000000000001631457410417000217220ustar00rootroot00000000000000# Adopt pre-commit https://github.com/jupyter/jupyter_kernel_test/pull/73 0f56150ddb3775fcbcf114a205a4ceb8c469e492 jupyter_kernel_test-0.7.0/.github/000077500000000000000000000000001457410417000171625ustar00rootroot00000000000000jupyter_kernel_test-0.7.0/.github/dependabot.yml000066400000000000000000000005071457410417000220140ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" groups: actions: patterns: - "*" - package-ecosystem: "pip" directory: "/" schedule: interval: "weekly" groups: actions: patterns: - "*" jupyter_kernel_test-0.7.0/.github/workflows/000077500000000000000000000000001457410417000212175ustar00rootroot00000000000000jupyter_kernel_test-0.7.0/.github/workflows/enforce-label.yml000066400000000000000000000005001457410417000244330ustar00rootroot00000000000000name: 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 jupyter_kernel_test-0.7.0/.github/workflows/prep-release.yml000066400000000000000000000032311457410417000243250ustar00rootroot00000000000000name: "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 silent: description: "Set a placeholder in the changelog and don't publish the release." required: false type: boolean 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 permissions: contents: write 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.GITHUB_TOKEN }} version_spec: ${{ github.event.inputs.version_spec }} silent: ${{ github.event.inputs.silent }} 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 }}" jupyter_kernel_test-0.7.0/.github/workflows/publish-changelog.yml000066400000000000000000000016401457410417000253360ustar00rootroot00000000000000name: "Publish Changelog" on: release: types: [published] workflow_dispatch: inputs: branch: description: "The branch to target" required: false jobs: publish_changelog: runs-on: ubuntu-latest environment: release steps: - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - uses: actions/create-github-app-token@v1 id: app-token with: app-id: ${{ vars.APP_ID }} private-key: ${{ secrets.APP_PRIVATE_KEY }} - name: Publish changelog id: publish-changelog uses: jupyter-server/jupyter_releaser/.github/actions/publish-changelog@v2 with: token: ${{ steps.app-token.outputs.token }} branch: ${{ github.event.inputs.branch }} - name: "** Next Step **" run: | echo "Merge the changelog update PR: ${{ steps.publish-changelog.outputs.pr_url }}" jupyter_kernel_test-0.7.0/.github/workflows/publish-release.yml000066400000000000000000000034061457410417000250310ustar00rootroot00000000000000name: "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 environment: release permissions: id-token: write steps: - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - uses: actions/create-github-app-token@v1 id: app-token with: app-id: ${{ vars.APP_ID }} private-key: ${{ secrets.APP_PRIVATE_KEY }} - name: Populate Release id: populate-release uses: jupyter-server/jupyter_releaser/.github/actions/populate-release@v2 with: token: ${{ steps.app-token.outputs.token }} 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 uses: jupyter-server/jupyter_releaser/.github/actions/finalize-release@v2 with: token: ${{ steps.app-token.outputs.token }} 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 }} jupyter_kernel_test-0.7.0/.github/workflows/tests.yml000066400000000000000000000101731457410417000231060ustar00rootroot00000000000000name: Tests on: push: pull_request: workflow_dispatch: schedule: - cron: "0 0 * * *" concurrency: group: tests-${{ github.ref }} cancel-in-progress: true defaults: run: shell: bash -l {0} jobs: test: name: Test runs-on: ${{ matrix.os }} timeout-minutes: 15 strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] python-version: ["3.8", "3.12"] include: - os: windows-latest python-version: "3.9" - os: macos-latest python-version: "3.11" - os: ubuntu-latest python-version: "3.10" env: OS: ${{ matrix.os }} steps: - name: Checkout uses: actions/checkout@v4 - name: Base setup uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - name: Setup conda ${{ matrix.python-version }} uses: conda-incubator/setup-miniconda@v3 with: auto-update-conda: true environment-file: environment.yml activate-environment: jupyter_kernel_test python-version: ${{ matrix.python-version }} # Xeus Cling Kernel Test is not working - times out. # - name: Install xeus-cling # if: startsWith(runner.os, 'Linux') # run: | # conda install -c conda-forge xeus-cling - name: Run the tests run: hatch run test:test || hatch run test:test test_minimum_versions: name: Test Minimum Versions timeout-minutes: 20 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 with: dependency_type: minimum - name: Run the unit tests run: | hatch run test:test || hatch run test:test test_prereleases: name: Test Prereleases runs-on: ubuntu-latest timeout-minutes: 20 steps: - uses: actions/checkout@v4 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 with: dependency_type: pre - name: Run the tests run: | hatch run test:test || hatch run test:test make_sdist: name: Make SDist runs-on: ubuntu-latest timeout-minutes: 10 steps: - uses: actions/checkout@v4 - 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: 15 steps: - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - uses: jupyterlab/maintainer-tools/.github/actions/test-sdist@v1 with: test_command: hatch run test:test || hatch run test:test check_links: runs-on: ubuntu-latest timeout-minutes: 10 steps: - uses: actions/checkout@v4 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - uses: jupyterlab/maintainer-tools/.github/actions/check-links@v1 test_lint: name: Test Lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - name: Run Linters run: | hatch run typing:test hatch run lint:build pipx run 'validate-pyproject[all]' pyproject.toml check_release: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - name: Check Release uses: jupyter-server/jupyter_releaser/.github/actions/check-release@v2 with: token: ${{ secrets.GITHUB_TOKEN }} tests_check: # This job does nothing and is only used for the branch protection if: always() needs: - test - test_lint - check_release - test_minimum_versions - test_prereleases - check_links - 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) }} jupyter_kernel_test-0.7.0/.gitignore000066400000000000000000000000341457410417000176070ustar00rootroot00000000000000__pycache__/ /build/ /dist/ jupyter_kernel_test-0.7.0/.pre-commit-config.yaml000066400000000000000000000042461457410417000221110ustar00rootroot00000000000000ci: autoupdate_schedule: monthly autoupdate_commit_msg: "chore: update pre-commit hooks" repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.5.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.27.4 hooks: - id: check-github-workflows - repo: https://github.com/executablebooks/mdformat rev: 0.7.17 hooks: - id: mdformat additional_dependencies: [mdformat-gfm, mdformat-frontmatter, mdformat-footnote] - repo: https://github.com/pre-commit/mirrors-prettier rev: "v4.0.0-alpha.8" hooks: - id: prettier types_or: [yaml, html, json] - repo: https://github.com/adamchainz/blacken-docs rev: "1.16.0" hooks: - id: blacken-docs additional_dependencies: [black==23.7.0] - repo: https://github.com/codespell-project/codespell rev: "v2.2.6" hooks: - id: codespell args: ["-L", "sur,nd"] - repo: https://github.com/pre-commit/pygrep-hooks rev: "v1.10.0" hooks: - id: rst-backticks - id: rst-directive-colons - id: rst-inline-touching-normal - repo: https://github.com/pre-commit/mirrors-mypy rev: "v1.8.0" hooks: - id: mypy files: "^jupyter_kernel_test" stages: [manual] args: ["--install-types", "--non-interactive"] additional_dependencies: ["jupyter_client"] - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.2.0 hooks: - id: ruff types_or: [python, jupyter] args: ["--fix", "--show-fixes"] - id: ruff-format types_or: [python, jupyter] - repo: https://github.com/scientific-python/cookie rev: "2024.01.24" hooks: - id: sp-repo-review additional_dependencies: ["repo-review[cli]"] jupyter_kernel_test-0.7.0/CHANGELOG.md000066400000000000000000000416611457410417000174430ustar00rootroot00000000000000# Changelog ## 0.7.0 ([Full Changelog](https://github.com/jupyter/jupyter_kernel_test/compare/v0.6.0...d3955dc57fff27ea45003b7720d511ce2803f3a4)) ### Maintenance and upkeep improvements - Update Release Scripts [#148](https://github.com/jupyter/jupyter_kernel_test/pull/148) ([@blink1073](https://github.com/blink1073)) - chore: update pre-commit hooks [#147](https://github.com/jupyter/jupyter_kernel_test/pull/147) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - Update ruff config [#146](https://github.com/jupyter/jupyter_kernel_test/pull/146) ([@blink1073](https://github.com/blink1073)) - chore: update pre-commit hooks [#145](https://github.com/jupyter/jupyter_kernel_test/pull/145) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - Bump conda-incubator/setup-miniconda from 2 to 3 [#144](https://github.com/jupyter/jupyter_kernel_test/pull/144) ([@dependabot](https://github.com/dependabot)) - chore: update pre-commit hooks [#143](https://github.com/jupyter/jupyter_kernel_test/pull/143) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - Clean up lint handling [#142](https://github.com/jupyter/jupyter_kernel_test/pull/142) ([@blink1073](https://github.com/blink1073)) - Adopt ruff format [#141](https://github.com/jupyter/jupyter_kernel_test/pull/141) ([@blink1073](https://github.com/blink1073)) - chore: update pre-commit hooks [#140](https://github.com/jupyter/jupyter_kernel_test/pull/140) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - Adopt sp-repo-review [#139](https://github.com/jupyter/jupyter_kernel_test/pull/139) ([@blink1073](https://github.com/blink1073)) - Bump actions/checkout from 3 to 4 [#137](https://github.com/jupyter/jupyter_kernel_test/pull/137) ([@dependabot](https://github.com/dependabot)) ### Contributors to this release ([GitHub contributors page for this release](https://github.com/jupyter/jupyter_kernel_test/graphs/contributors?from=2023-08-29&to=2024-03-12&type=c)) [@blink1073](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Ablink1073+updated%3A2023-08-29..2024-03-12&type=Issues) | [@dependabot](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Adependabot+updated%3A2023-08-29..2024-03-12&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Apre-commit-ci+updated%3A2023-08-29..2024-03-12&type=Issues) ## 0.6.0 ([Full Changelog](https://github.com/jupyter/jupyter_kernel_test/compare/v0.5.0...78b8f14cf8a7f6c4fba4cb20edd8fa293ae7a602)) ### Enhancements made - Add test for Jep #65 [#134](https://github.com/jupyter/jupyter_kernel_test/pull/134) ([@Hind-M](https://github.com/Hind-M)) ### Maintenance and upkeep improvements - Drop Python 3.7 support [#135](https://github.com/jupyter/jupyter_kernel_test/pull/135) ([@blink1073](https://github.com/blink1073)) - Add more linting [#127](https://github.com/jupyter/jupyter_kernel_test/pull/127) ([@blink1073](https://github.com/blink1073)) ### Contributors to this release ([GitHub contributors page for this release](https://github.com/jupyter/jupyter_kernel_test/graphs/contributors?from=2023-01-27&to=2023-08-29&type=c)) [@blink1073](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Ablink1073+updated%3A2023-01-27..2023-08-29&type=Issues) | [@Hind-M](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3AHind-M+updated%3A2023-01-27..2023-08-29&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Apre-commit-ci+updated%3A2023-01-27..2023-08-29&type=Issues) ## 0.5.0 ([Full Changelog](https://github.com/jupyter/jupyter_kernel_test/compare/v0.4.5...c3ffbd013b1cdd32d7273d4fbe9ee0ab61af7a1e)) ### Maintenance and upkeep improvements - Upgrade lint [#126](https://github.com/jupyter/jupyter_kernel_test/pull/126) ([@blink1073](https://github.com/blink1073)) - Adopt ruff and address lint [#123](https://github.com/jupyter/jupyter_kernel_test/pull/123) ([@blink1073](https://github.com/blink1073)) - Use base setup dependency type [#120](https://github.com/jupyter/jupyter_kernel_test/pull/120) ([@blink1073](https://github.com/blink1073)) - Fix test invocation [#118](https://github.com/jupyter/jupyter_kernel_test/pull/118) ([@blink1073](https://github.com/blink1073)) - CI Cleanup [#117](https://github.com/jupyter/jupyter_kernel_test/pull/117) ([@blink1073](https://github.com/blink1073)) - Bump actions/checkout from 2 to 3 [#115](https://github.com/jupyter/jupyter_kernel_test/pull/115) ([@dependabot](https://github.com/dependabot)) - Add dependabot [#114](https://github.com/jupyter/jupyter_kernel_test/pull/114) ([@blink1073](https://github.com/blink1073)) - Maintenance cleanup [#111](https://github.com/jupyter/jupyter_kernel_test/pull/111) ([@blink1073](https://github.com/blink1073)) - Fix client 8 compat [#109](https://github.com/jupyter/jupyter_kernel_test/pull/109) ([@blink1073](https://github.com/blink1073)) - Maintenance clean up [#106](https://github.com/jupyter/jupyter_kernel_test/pull/106) ([@blink1073](https://github.com/blink1073)) ### Contributors to this release ([GitHub contributors page for this release](https://github.com/jupyter/jupyter_kernel_test/graphs/contributors?from=2022-08-22&to=2023-01-27&type=c)) [@blink1073](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Ablink1073+updated%3A2022-08-22..2023-01-27&type=Issues) | [@dependabot](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Adependabot+updated%3A2022-08-22..2023-01-27&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Apre-commit-ci+updated%3A2022-08-22..2023-01-27&type=Issues) ## 0.4.5 ([Full Changelog](https://github.com/jupyter/jupyter_kernel_test/compare/v0.4.4...85c23f820f8127808f60dab6f5871e8d26c01192)) ### Maintenance and upkeep improvements - Switch to hatch backend [#100](https://github.com/jupyter/jupyter_kernel_test/pull/100) ([@blink1073](https://github.com/blink1073)) ### Contributors to this release ([GitHub contributors page for this release](https://github.com/jupyter/jupyter_kernel_test/graphs/contributors?from=2022-08-19&to=2022-08-22&type=c)) [@blink1073](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Ablink1073+updated%3A2022-08-19..2022-08-22&type=Issues) ## 0.4.4 ([Full Changelog](https://github.com/jupyter/jupyter_kernel_test/compare/v0.4.3...b723ce668df0de185f9b682d85379e515cfc012b)) ### Maintenance and upkeep improvements - Stop testing xeus cling [#97](https://github.com/jupyter/jupyter_kernel_test/pull/97) ([@blink1073](https://github.com/blink1073)) - \[pre-commit.ci\] pre-commit autoupdate [#96](https://github.com/jupyter/jupyter_kernel_test/pull/96) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - Fix flake8 v5 compat [#95](https://github.com/jupyter/jupyter_kernel_test/pull/95) ([@blink1073](https://github.com/blink1073)) - \[pre-commit.ci\] pre-commit autoupdate [#94](https://github.com/jupyter/jupyter_kernel_test/pull/94) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - \[pre-commit.ci\] pre-commit autoupdate [#92](https://github.com/jupyter/jupyter_kernel_test/pull/92) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - \[pre-commit.ci\] pre-commit autoupdate [#91](https://github.com/jupyter/jupyter_kernel_test/pull/91) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - \[pre-commit.ci\] pre-commit autoupdate [#90](https://github.com/jupyter/jupyter_kernel_test/pull/90) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - \[pre-commit.ci\] pre-commit autoupdate [#89](https://github.com/jupyter/jupyter_kernel_test/pull/89) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - \[pre-commit.ci\] pre-commit autoupdate [#88](https://github.com/jupyter/jupyter_kernel_test/pull/88) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - \[pre-commit.ci\] pre-commit autoupdate [#87](https://github.com/jupyter/jupyter_kernel_test/pull/87) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - \[pre-commit.ci\] pre-commit autoupdate [#86](https://github.com/jupyter/jupyter_kernel_test/pull/86) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - \[pre-commit.ci\] pre-commit autoupdate [#85](https://github.com/jupyter/jupyter_kernel_test/pull/85) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - \[pre-commit.ci\] pre-commit autoupdate [#84](https://github.com/jupyter/jupyter_kernel_test/pull/84) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - \[pre-commit.ci\] pre-commit autoupdate [#83](https://github.com/jupyter/jupyter_kernel_test/pull/83) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - Enable auto-label for bot PRs [#82](https://github.com/jupyter/jupyter_kernel_test/pull/82) ([@blink1073](https://github.com/blink1073)) - \[pre-commit.ci\] pre-commit autoupdate [#81](https://github.com/jupyter/jupyter_kernel_test/pull/81) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - Run tests twice [#80](https://github.com/jupyter/jupyter_kernel_test/pull/80) ([@blink1073](https://github.com/blink1073)) - Use flit build backend [#79](https://github.com/jupyter/jupyter_kernel_test/pull/79) ([@blink1073](https://github.com/blink1073)) - \[pre-commit.ci\] pre-commit autoupdate [#78](https://github.com/jupyter/jupyter_kernel_test/pull/78) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - \[pre-commit.ci\] pre-commit autoupdate [#77](https://github.com/jupyter/jupyter_kernel_test/pull/77) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - \[pre-commit.ci\] pre-commit autoupdate [#76](https://github.com/jupyter/jupyter_kernel_test/pull/76) ([@pre-commit-ci](https://github.com/pre-commit-ci)) - Adopt flake8 and update ci [#75](https://github.com/jupyter/jupyter_kernel_test/pull/75) ([@blink1073](https://github.com/blink1073)) - Add git-blame-ignore-revs [#74](https://github.com/jupyter/jupyter_kernel_test/pull/74) ([@blink1073](https://github.com/blink1073)) - Adopt pre-commit [#73](https://github.com/jupyter/jupyter_kernel_test/pull/73) ([@blink1073](https://github.com/blink1073)) - Drop support for py36 [#72](https://github.com/jupyter/jupyter_kernel_test/pull/72) ([@blink1073](https://github.com/blink1073)) - Fix typos [#71](https://github.com/jupyter/jupyter_kernel_test/pull/71) ([@martinRenou](https://github.com/martinRenou)) - Add xeus-cling test [#69](https://github.com/jupyter/jupyter_kernel_test/pull/69) ([@blink1073](https://github.com/blink1073)) ### Contributors to this release ([GitHub contributors page for this release](https://github.com/jupyter/jupyter_kernel_test/graphs/contributors?from=2021-12-06&to=2022-08-19&type=c)) [@blink1073](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Ablink1073+updated%3A2021-12-06..2022-08-19&type=Issues) | [@martinRenou](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3AmartinRenou+updated%3A2021-12-06..2022-08-19&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Apre-commit-ci+updated%3A2021-12-06..2022-08-19&type=Issues) ## 0.4.3 ([Full Changelog](https://github.com/jupyter/jupyter_kernel_test/compare/v0.4.2...77a01dc64e0449e026bc505948c3f773f7a01be3)) ### Maintenance and upkeep improvements - Clean up ci [#67](https://github.com/jupyter/jupyter_kernel_test/pull/67) ([@blink1073](https://github.com/blink1073)) ### Contributors to this release ([GitHub contributors page for this release](https://github.com/jupyter/jupyter_kernel_test/graphs/contributors?from=2021-12-05&to=2021-12-06&type=c)) [@blink1073](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Ablink1073+updated%3A2021-12-05..2021-12-06&type=Issues) ## 0.4.2 ([Full Changelog](https://github.com/jupyter/jupyter_kernel_test/compare/v0.4.1...fcc3d1e7eaf262a1dd5b3bce7b5e160bd1d69265)) ### Bugs fixed - Add minimum `jupyter_client` version [#64](https://github.com/jupyter/jupyter_kernel_test/pull/64) ([@blink1073](https://github.com/blink1073)) ### Contributors to this release ([GitHub contributors page for this release](https://github.com/jupyter/jupyter_kernel_test/graphs/contributors?from=2021-12-02&to=2021-12-05&type=c)) [@blink1073](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Ablink1073+updated%3A2021-12-02..2021-12-05&type=Issues) ## 0.4.1 ([Full Changelog](https://github.com/jupyter/jupyter_kernel_test/compare/v0.4.0...87bdb591a83640ec76fe74ce11611a821653d0a6)) ### Maintenance and upkeep improvements - Add more robustness [#62](https://github.com/jupyter/jupyter_kernel_test/pull/62) ([@blink1073](https://github.com/blink1073)) ### Contributors to this release ([GitHub contributors page for this release](https://github.com/jupyter/jupyter_kernel_test/graphs/contributors?from=2021-11-30&to=2021-12-02&type=c)) [@blink1073](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Ablink1073+updated%3A2021-11-30..2021-12-02&type=Issues) ## 0.4.0 ([Full Changelog](https://github.com/jupyter/jupyter_kernel_test/compare/0.3...687e6f83af9cecae832c4ad8f79291322def23e5)) ### Enhancements made - Use jsonschema to validate messages [#37](https://github.com/jupyter/jupyter_kernel_test/pull/37) ([@takluyver](https://github.com/takluyver)) ### Maintenance and upkeep improvements - Prep for jupyter releaser usage [#59](https://github.com/jupyter/jupyter_kernel_test/pull/59) ([@blink1073](https://github.com/blink1073)) - Test IR Kernel and Clean Up [#58](https://github.com/jupyter/jupyter_kernel_test/pull/58) ([@blink1073](https://github.com/blink1073)) - Update for Jupyter Client 7 and GitHub Actions [#57](https://github.com/jupyter/jupyter_kernel_test/pull/57) ([@blink1073](https://github.com/blink1073)) - Fix import issue with pytest [#46](https://github.com/jupyter/jupyter_kernel_test/pull/46) ([@martinRenou](https://github.com/martinRenou)) - Use new kernel management modules [#41](https://github.com/jupyter/jupyter_kernel_test/pull/41) ([@takluyver](https://github.com/takluyver)) - Replace COPYING.md with LICENCE file [#34](https://github.com/jupyter/jupyter_kernel_test/pull/34) ([@tgb417](https://github.com/tgb417)) - Fix custom test example in README [#49](https://github.com/jupyter/jupyter_kernel_test/pull/49) ([@kylebarron](https://github.com/kylebarron)) - Fix readme [#45](https://github.com/jupyter/jupyter_kernel_test/pull/45) ([@martinRenou](https://github.com/martinRenou)) ### Contributors to this release ([GitHub contributors page for this release](https://github.com/jupyter/jupyter_kernel_test/graphs/contributors?from=2017-04-28&to=2021-11-30&type=c)) [@blink1073](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Ablink1073+updated%3A2017-04-28..2021-11-30&type=Issues) | [@kylebarron](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Akylebarron+updated%3A2017-04-28..2021-11-30&type=Issues) | [@martinRenou](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3AmartinRenou+updated%3A2017-04-28..2021-11-30&type=Issues) | [@SylvainCorlay](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3ASylvainCorlay+updated%3A2017-04-28..2021-11-30&type=Issues) | [@takluyver](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Atakluyver+updated%3A2017-04-28..2021-11-30&type=Issues) | [@tgb417](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Atgb417+updated%3A2017-04-28..2021-11-30&type=Issues) ## 0.3 ([Full Changelog](https://github.com/jupyter/jupyter_kernel_test/compare/7283c8c...309feed)) ### Merged PRs - Add stop_on_error [#32](https://github.com/jupyter/jupyter_kernel_test/pull/32) ([@shzhng](https://github.com/shzhng)) - Update README.rst [#29](https://github.com/jupyter/jupyter_kernel_test/pull/29) ([@maveme](https://github.com/maveme)) - Made stdout/stderr tests less order dependent. [#28](https://github.com/jupyter/jupyter_kernel_test/pull/28) ([@mariusvniekerk](https://github.com/mariusvniekerk)) - Convert readthedocs links for their .org -> .io migration for hosted projects [#26](https://github.com/jupyter/jupyter_kernel_test/pull/26) ([@adamchainz](https://github.com/adamchainz)) ### Contributors to this release ([GitHub contributors page for this release](https://github.com/jupyter/jupyter_kernel_test/graphs/contributors?from=2016-06-13&to=2017-04-28&type=c)) [@adamchainz](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Aadamchainz+updated%3A2016-06-13..2017-04-28&type=Issues) | [@mariusvniekerk](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Amariusvniekerk+updated%3A2016-06-13..2017-04-28&type=Issues) | [@maveme](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Amaveme+updated%3A2016-06-13..2017-04-28&type=Issues) | [@shzhng](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Ashzhng+updated%3A2016-06-13..2017-04-28&type=Issues) | [@takluyver](https://github.com/search?q=repo%3Ajupyter%2Fjupyter_kernel_test+involves%3Atakluyver+updated%3A2016-06-13..2017-04-28&type=Issues) jupyter_kernel_test-0.7.0/LICENSE000066400000000000000000000027561457410417000166410ustar00rootroot00000000000000Copyright (c) 2015-2021 Project Jupyter Contributors 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. jupyter_kernel_test-0.7.0/README.rst000066400000000000000000000065441457410417000173220ustar00rootroot00000000000000=================== jupyter_kernel_test =================== ``jupyter_kernel_test`` is a tool for testing Jupyter_ kernels. It tests kernels for successful code execution and conformance with the `Jupyter Messaging Protocol`_ (currently 5.0). ------- Install ------- Install it with pip (python3.4 or greater required):: pip3 install jupyter_kernel_test ----- Usage ----- To use it, you need to write a (python) ``unittest`` file containing code samples in the relevant language which test various parts of the messaging protocol. A short example is given below, and you can also refer to the ``test_ipykernel.py`` and ``test_irkernel.py`` files for complete examples. Some parts of the messaging protocol are relevant only to the browser-based notebook (rich display) or console interfaces (code completeness, history searching). Only parts of the spec for which you provide code samples are tested. Run this file directly using python, or use ``nosetests`` or ``py.test`` to find and run it. ------- Example ------- .. code-block:: python import unittest import jupyter_kernel_test class MyKernelTests(jupyter_kernel_test.KernelTests): # Required -------------------------------------- # The name identifying an installed kernel to run the tests against kernel_name = "mykernel" # language_info.name in a kernel_info_reply should match this language_name = "mylanguage" # Optional -------------------------------------- # Code in the kernel's language to write "hello, world" to stdout code_hello_world = "print 'hello, world'" # Pager: code that should display something (anything) in the pager code_page_something = "help(something)" # Samples of code which generate a result value (ie, some text # displayed as Out[n]) code_execute_result = [{"code": "6*7", "result": "42"}] # Samples of code which should generate a rich display output, and # the expected MIME type code_display_data = [{"code": "show_image()", "mime": "image/png"}] # You can also write extra tests. We recommend putting your kernel name # in the method name, to avoid clashing with any tests that # jupyter_kernel_test adds in the future. def test_mykernel_stderr(self): self.flush_channels() reply, output_msgs = self.execute_helper(code='print_err "oops"') self.assertEqual(output_msgs[0]["header"]["msg_type"], "stream") self.assertEqual(output_msgs[0]["content"]["name"], "stderr") self.assertEqual(output_msgs[0]["content"]["text"], "oops\n") if __name__ == "__main__": unittest.main() -------- Coverage -------- The following aspects of the messaging protocol are not explicitly tested: - Widget comms: ``comm_open``, ``comm_msg``, ``comm_close`` - stdin: ``input_request``, ``input_reply`` - display_data metadata - Shutdown/restart: ``shutdown_request``, ``shutdown_reply`` - History: not all option combinations covered - Inspection: multiple levels - Execution payloads (deprecated but still used): payloads ``load``, ``edit``, ``ask_exit`` - User expressions - Execution: combinations of ``silent``, ``store_history`` and ``stop_on_error`` .. _Jupyter: http://jupyter.org .. _Jupyter Messaging Protocol: https://jupyter-client.readthedocs.io/en/latest/messaging.html jupyter_kernel_test-0.7.0/RELEASE.md000066400000000000000000000010031457410417000172160ustar00rootroot00000000000000# Release Guide ## Using `jupyter_releaser` The recommended way to make a release is to use [`jupyter_releaser`](https://github.com/jupyter-server/jupyter_releaser#checklist-for-adoption). ## Manual Release - Update `CHANGELOG` - Run the following: ```bash export VERSION= pip install jupyter_releaser tbump --only-patch $VERSION git commit -a -m "Release $VERSION" git tag $VERSION; true; git push --all git push --tags rm -rf dist build python -m build . twine check dist/* twine upload dist/* ``` jupyter_kernel_test-0.7.0/environment.yml000066400000000000000000000002041457410417000207050ustar00rootroot00000000000000name: jupyter_kernel_test channels: - conda-forge dependencies: - r-recommended - r-irkernel - pip - setuptools - wheel jupyter_kernel_test-0.7.0/jupyter_kernel_test/000077500000000000000000000000001457410417000217235ustar00rootroot00000000000000jupyter_kernel_test-0.7.0/jupyter_kernel_test/__init__.py000066400000000000000000000401341457410417000240360ustar00rootroot00000000000000"""Machinery for testing Jupyter kernels via the messaging protocol. """ # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. from __future__ import annotations import inspect from queue import Empty from typing import Any from unittest import SkipTest, TestCase from jupyter_client.blocking.client import BlockingKernelClient from jupyter_client.manager import KernelManager, start_new_kernel from jupyter_client.utils import run_sync # type:ignore[attr-defined] from .msgspec_v5 import validate_message TIMEOUT = 15 __version__ = "0.7.0" def ensure_sync(func: Any) -> Any: if inspect.iscoroutinefunction(func): return run_sync(func) return func class KernelTests(TestCase): kernel_name = "python3" kc: BlockingKernelClient km: KernelManager @classmethod def setUpClass(cls) -> None: cls.km, cls.kc = start_new_kernel(kernel_name=cls.kernel_name) @classmethod def tearDownClass(cls) -> None: cls.kc.stop_channels() cls.km.shutdown_kernel() def flush_channels(self) -> None: for channel in (self.kc.shell_channel, self.kc.iopub_channel): while True: try: msg = ensure_sync(channel.get_msg)(timeout=0.1) except TypeError: msg = channel.get_msg(timeout=0.1) except Empty: break else: validate_message(msg) language_name = "" file_extension = "" def test_kernel_info(self) -> None: self.flush_channels() msg_id = self.kc.kernel_info() reply = self.kc.get_shell_msg(timeout=TIMEOUT) validate_message(reply, "kernel_info_reply", msg_id) if self.language_name: self.assertEqual(reply["content"]["language_info"]["name"], self.language_name) if self.file_extension: self.assertEqual( reply["content"]["language_info"]["file_extension"], self.file_extension ) self.assertTrue(reply["content"]["language_info"]["file_extension"].startswith(".")) def execute_helper( self, code: str, timeout: int = TIMEOUT, silent: bool = False, store_history: bool = True, stop_on_error: bool = True, ) -> tuple[dict[str, Any], list[dict[str, Any]]]: msg_id = self.kc.execute( code=code, silent=silent, store_history=store_history, stop_on_error=stop_on_error ) reply = self.get_non_kernel_info_reply(timeout=timeout) assert reply is not None validate_message(reply, "execute_reply", msg_id) busy_msg = ensure_sync(self.kc.iopub_channel.get_msg)(timeout=1) validate_message(busy_msg, "status", msg_id) self.assertEqual(busy_msg["content"]["execution_state"], "busy") output_msgs = [] while True: msg = ensure_sync(self.kc.iopub_channel.get_msg)(timeout=0.1) validate_message(msg, msg["msg_type"], msg_id) if msg["msg_type"] == "status": self.assertEqual(msg["content"]["execution_state"], "idle") break if msg["msg_type"] == "execute_input": self.assertEqual(msg["content"]["code"], code) continue output_msgs.append(msg) return reply, output_msgs code_hello_world = "" def test_execute_stdout(self) -> None: if not self.code_hello_world: raise SkipTest("No code hello world") self.flush_channels() reply, output_msgs = self.execute_helper(code=self.code_hello_world) self.assertEqual(reply["content"]["status"], "ok") self.assertGreaterEqual(len(output_msgs), 1) for msg in output_msgs: if (msg["msg_type"] == "stream") and (msg["content"]["name"] == "stdout"): self.assertIn("hello, world", msg["content"]["text"]) break else: self.assertTrue( False, "Expected one output message of type 'stream' and 'content.name'='stdout'" ) code_stderr = "" def test_execute_stderr(self) -> None: if not self.code_stderr: raise SkipTest("No code stderr") self.flush_channels() reply, output_msgs = self.execute_helper(code=self.code_stderr) self.assertEqual(reply["content"]["status"], "ok") self.assertGreaterEqual(len(output_msgs), 1) for msg in output_msgs: if (msg["msg_type"] == "stream") and (msg["content"]["name"] == "stderr"): break else: self.assertTrue( False, "Expected one output message of type 'stream' and 'content.name'='stderr'" ) completion_samples: list[dict[str, Any]] = [] def get_non_kernel_info_reply(self, timeout: float | None = None) -> dict[str, Any] | None: while True: reply = self.kc.get_shell_msg(timeout=timeout) if reply["header"]["msg_type"] != "kernel_info_reply": return reply def test_completion(self) -> None: if not self.completion_samples: raise SkipTest("No completion samples") for sample in self.completion_samples: with self.subTest(text=sample["text"]): msg_id = self.kc.complete(sample["text"]) reply = self.get_non_kernel_info_reply() validate_message(reply, "complete_reply", msg_id) assert reply is not None if "matches" in sample: self.assertEqual(set(reply["content"]["matches"]), set(sample["matches"])) complete_code_samples: list[str] = [] incomplete_code_samples: list[str] = [] invalid_code_samples: list[str] = [] def check_is_complete(self, sample: str, status: str) -> None: msg_id = self.kc.is_complete(sample) reply = self.get_non_kernel_info_reply() validate_message(reply, "is_complete_reply", msg_id) assert reply is not None if reply["content"]["status"] != status: msg = "For code sample\n {!r}\nExpected {!r}, got {!r}." raise AssertionError(msg.format(sample, status, reply["content"]["status"])) def test_is_complete(self) -> None: if not ( self.complete_code_samples or self.incomplete_code_samples or self.invalid_code_samples ): raise SkipTest("Not testing is_complete") self.flush_channels() with self.subTest(status="complete"): for sample in self.complete_code_samples: self.check_is_complete(sample, "complete") with self.subTest(status="incomplete"): for sample in self.incomplete_code_samples: self.check_is_complete(sample, "incomplete") with self.subTest(status="invalid"): for sample in self.invalid_code_samples: self.check_is_complete(sample, "invalid") code_page_something = "" def test_pager(self) -> None: if not self.code_page_something: raise SkipTest("No code page something") self.flush_channels() reply, output_msgs = self.execute_helper(self.code_page_something) self.assertEqual(reply["content"]["status"], "ok") payloads = reply["content"]["payload"] self.assertEqual(len(payloads), 1) self.assertEqual(payloads[0]["source"], "page") mimebundle = payloads[0]["data"] self.assertIn("text/plain", mimebundle) code_generate_error = "" def test_error(self) -> None: if not self.code_generate_error: raise SkipTest("No code generate error") self.flush_channels() reply, output_msgs = self.execute_helper(self.code_generate_error) self.assertEqual(reply["content"]["status"], "error") self.assertEqual(len(output_msgs), 1) self.assertEqual(output_msgs[0]["msg_type"], "error") code_execute_result: list[dict[str, str]] = [] def test_execute_result(self) -> None: if not self.code_execute_result: raise SkipTest("No code execute result") for sample in self.code_execute_result: with self.subTest(code=sample["code"]): self.flush_channels() reply, output_msgs = self.execute_helper(sample["code"]) self.assertEqual(reply["content"]["status"], "ok") self.assertGreaterEqual(len(output_msgs), 1) found = False for msg in output_msgs: if msg["msg_type"] == "execute_result": found = True else: continue mime = sample.get("mime", "text/plain") self.assertIn(mime, msg["content"]["data"]) if "result" in sample: self.assertEqual(msg["content"]["data"][mime], sample["result"]) if not found: emsg = "execute_result message not found" raise AssertionError(emsg) code_display_data: list[dict[str, str]] = [] def test_display_data(self) -> None: if not self.code_display_data: raise SkipTest("No code display data") for sample in self.code_display_data: with self.subTest(code=sample["code"]): self.flush_channels() reply, output_msgs = self.execute_helper(sample["code"]) self.assertEqual(reply["content"]["status"], "ok") self.assertGreaterEqual(len(output_msgs), 1) found = False for msg in output_msgs: if msg["msg_type"] == "display_data": found = True else: continue self.assertIn(sample["mime"], msg["content"]["data"]) if not found: emsg = "display_data message not found" raise AssertionError(emsg) # this should match one of the values in code_execute_result code_history_pattern = "" supported_history_operations = () def history_helper( self, execute_first: Any, timeout: float | None = TIMEOUT, **histargs: Any ) -> dict[str, Any]: self.flush_channels() for code in execute_first: self.execute_helper(code) self.flush_channels() msg_id = self.kc.history(**histargs) reply = self.get_non_kernel_info_reply(timeout=timeout) validate_message(reply, "history_reply", msg_id) assert reply is not None return reply def test_history(self) -> None: if not self.code_execute_result: raise SkipTest("No code execute result") codes = [s["code"] for s in self.code_execute_result] _ = [s.get("result", "") for s in self.code_execute_result] n = len(codes) session = start = None with self.subTest(hist_access_type="tail"): if "tail" not in self.supported_history_operations: raise SkipTest("History tail not supported") reply = self.history_helper(codes, output=False, raw=True, hist_access_type="tail", n=n) self.assertEqual(len(reply["content"]["history"]), n) self.assertEqual(len(reply["content"]["history"][0]), 3) self.assertEqual(codes, [h[2] for h in reply["content"]["history"]]) session, start = reply["content"]["history"][0][0:2] with self.subTest(output=True): reply = self.history_helper( codes, output=True, raw=True, hist_access_type="tail", n=n ) self.assertEqual(len(reply["content"]["history"][0][2]), 2) with self.subTest(hist_access_type="range"): if "range" not in self.supported_history_operations: raise SkipTest("History range not supported") if session is None: raise SkipTest("No session") reply = self.history_helper( codes, output=False, raw=True, hist_access_type="range", session=session, start=start, stop=start + 1, ) self.assertEqual(len(reply["content"]["history"]), 1) self.assertEqual(reply["content"]["history"][0][0], session) self.assertEqual(reply["content"]["history"][0][1], start) with self.subTest(hist_access_type="search"): if not self.code_history_pattern: raise SkipTest("No code history pattern") if "search" not in self.supported_history_operations: raise SkipTest("History search not supported") with self.subTest(subsearch="normal"): reply = self.history_helper( codes, output=False, raw=True, hist_access_type="search", pattern=self.code_history_pattern, ) self.assertGreaterEqual(len(reply["content"]["history"]), 1) with self.subTest(subsearch="unique"): reply = self.history_helper( codes, output=False, raw=True, hist_access_type="search", pattern=self.code_history_pattern, unique=True, ) self.assertEqual(len(reply["content"]["history"]), 1) with self.subTest(subsearch="n"): reply = self.history_helper( codes, output=False, raw=True, hist_access_type="search", pattern=self.code_history_pattern, n=3, ) self.assertEqual(len(reply["content"]["history"]), 3) code_inspect_sample = "" def test_inspect(self) -> None: if not self.code_inspect_sample: raise SkipTest("No code inspect sample") self.flush_channels() msg_id = self.kc.inspect(self.code_inspect_sample) reply = self.get_non_kernel_info_reply(timeout=TIMEOUT) validate_message(reply, "inspect_reply", msg_id) assert reply is not None self.assertEqual(reply["content"]["status"], "ok") self.assertTrue(reply["content"]["found"]) self.assertGreaterEqual(len(reply["content"]["data"]), 1) code_clear_output = "" def test_clear_output(self) -> None: if not self.code_clear_output: raise SkipTest("No code clear output") self.flush_channels() reply, output_msgs = self.execute_helper(code=self.code_clear_output) self.assertEqual(reply["content"]["status"], "ok") self.assertGreaterEqual(len(output_msgs), 1) found = False for msg in output_msgs: if msg["msg_type"] == "clear_output": found = True else: continue if not found: emsg = "clear_output message not found" raise AssertionError(emsg) class IopubWelcomeTests(TestCase): kernel_name = "python3" kc: BlockingKernelClient km: KernelManager @classmethod def setUpClass(cls) -> None: cls.km = KernelManager(kernel_name=cls.kernel_name) cls.km.start_kernel() cls.kc = cls.km.client() @classmethod def tearDownClass(cls) -> None: cls.kc.stop_channels() cls.km.shutdown_kernel() support_iopub_welcome = False def test_recv_iopub_welcome_msg(self) -> None: if not self.support_iopub_welcome: raise SkipTest("Iopub welcome messages are not supported") self.kc.start_channels() while True: msg = self.kc.get_iopub_msg() if msg: self.assertEqual(msg["header"]["msg_type"], "iopub_welcome") self.assertEqual(msg["msg_type"], "iopub_welcome") self.assertEqual( msg["content"]["subscription"], "" ) # Default: empty topic means subscription to all topics break jupyter_kernel_test-0.7.0/jupyter_kernel_test/msgspec_v5.py000066400000000000000000000310611457410417000243510ustar00rootroot00000000000000"""Message schemas for message spec version 5""" # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. from __future__ import annotations import re from typing import Any from jsonschema import Draft4Validator, ValidationError protocol_version = (5, 1) # These fragments will be wrapped in the boilerplate for a valid JSON schema. # We also add a default 'required' containing all keys. schema_fragments: dict[str, Any] = {} def get_msg_content_validator(msg_type: str, version_minor: int) -> Draft4Validator: frag = schema_fragments[msg_type] schema: dict[str, Any] = { "$schema": "http://json-schema.org/draft-04/schema#", "description": f"{msg_type} message contents schema", "type": "object", "properties": {}, "additionalProperties": version_minor > protocol_version[1], } schema.update(frag) if "required" not in schema: # Require all keys by default schema["required"] = sorted(schema["properties"].keys()) return Draft4Validator(schema) header_part = { "type": "object", "properties": { "msg_id": {"type": "string"}, "username": {"type": "string"}, "session": {"type": "string"}, # TODO - this is parsed to a datetime before we get it: "date": {}, # {"type": "string"}, "msg_type": {"type": "string"}, "version": {"type": "string"}, }, "required": ["msg_id", "username", "session", "date", "msg_type", "version"], } msg_schema = { "$schema": "http://json-schema.org/draft-04/schema#", "description": "Jupyter message structure schema", "type": "object", "properties": { "header": header_part, "parent_header": {"type": "object"}, "metadata": {"type": "object"}, "content": {"type": "object"}, # Checked separately "buffers": {"type": "array"}, }, "required": ["header", "parent_header", "metadata", "content"], } msg_structure_validator = Draft4Validator(msg_schema) def get_error_reply_validator(version_minor: int) -> Draft4Validator: return Draft4Validator( { "$schema": "http://json-schema.org/draft-04/schema#", "description": "Jupyter 'error' reply schema", "type": "object", "properties": { "status": {"const": "error"}, "ename": {"type": "string"}, "evalue": {"type": "string"}, "traceback": {"type": "array", "items": {"type": "string"}}, }, "required": ["status", "ename", "evalue", "traceback"], "additionalProperties": version_minor > protocol_version[1], } ) def get_abort_reply_validator(version_minor: int) -> Draft4Validator: return Draft4Validator( { "$schema": "http://json-schema.org/draft-04/schema#", "description": "Jupyter 'abort' reply schema", "type": "object", "properties": { "status": {"const": "error"}, "ename": {"type": "string"}, "evalue": {"type": "string"}, "traceback": {"type": "list", "items": {"type": "string"}}, }, "required": ["status", "ename", "evalue", "traceback"], "additionalProperties": version_minor > protocol_version[1], } ) reply_msgs_using_status = { "execute_reply", "inspect_reply", "complete_reply", "history_reply", "connect_reply", "comm_info_reply", "kernel_info_reply", "shutdown_reply", "interrupt_reply", } def validate_message( msg: dict[str, Any] | None, msg_type: str | None = None, parent_id: str | None = None ) -> None: msg_structure_validator.validate(msg) assert msg is not None msg_version_s = msg["header"]["version"] m = re.match(r"(\d+)\.(\d+)", msg_version_s) if not m: emsg = "Version {} not like 'x.y'" raise ValidationError(emsg) version_minor = int(m.group(2)) if msg_type is not None: if msg["header"]["msg_type"] != msg_type: emsg = "Message type {!r} != {!r}".format(msg["header"]["msg_type"], msg_type) raise ValidationError(emsg) else: msg_type = msg["header"]["msg_type"] # Check for unexpected fields, unless it's a newer protocol version if version_minor <= protocol_version[1]: unx_top = set(msg) - set(msg_schema["properties"]) if unx_top: emsg = f"Unexpected keys: {unx_top}" raise ValidationError(emsg) unx_header = set(msg["header"]) - set(header_part["properties"]) if unx_header: emsg = f"Unexpected keys in header: {unx_header}" raise ValidationError(emsg) # Check the parent id if "reply" in msg_type and parent_id and msg["parent_header"]["msg_id"] != parent_id: emsg = "Parent header does not match expected" raise ValidationError(emsg) if msg_type in reply_msgs_using_status: # Most _reply messages have common 'error' and 'abort' structures try: status = msg["content"]["status"] except KeyError as e: raise ValidationError(str(e)) from None if status == "error": content_vdor = get_error_reply_validator(version_minor) elif status == "abort": content_vdor = get_abort_reply_validator(version_minor) elif status == "ok": content_vdor = get_msg_content_validator(msg_type, version_minor) else: emsg = f"status {status!r} should be ok/error/abort" raise ValidationError(emsg) else: content_vdor = get_msg_content_validator(msg_type, version_minor) content_vdor.validate(msg["content"]) # Shell messages ---------------------------------------------- schema_fragments["execute_request"] = { "properties": { "code": {"type": "string"}, "silent": {"type": "boolean"}, "store_history": {"type": "boolean"}, "user_expressions": {"type": "object"}, "allow_stdin": {"type": "boolean"}, "stop_on_error": {"type": "boolean"}, } } schema_fragments["execute_reply"] = { "properties": { # statuses 'error' and 'abort' change the structure, so check separately "status": {"const": "ok"}, "execution_count": {"type": "number"}, "payload": { "type": "array", "items": { "type": "object", "properties": {"source": {"type": "string"}}, "additionalProperties": True, }, }, "user_expressions": {"type": "object"}, }, "required": ["status", "execution_count"], } schema_fragments["inspect_request"] = { "properties": { "code": {"type": "string"}, "cursor_pos": {"type": "number"}, "detail_level": {"enum": [0, 1]}, } } schema_fragments["inspect_reply"] = { "properties": { # statuses 'error' and 'abort' change the structure, so check separately "status": {"const": "ok"}, "found": {"type": "boolean"}, "data": {"type": "object"}, "metadata": {"type": "object"}, } } schema_fragments["complete_request"] = { "properties": { "code": {"type": "string"}, "cursor_pos": {"type": "number"}, } } schema_fragments["complete_reply"] = { "properties": { # statuses 'error' and 'abort' change the structure, so check separately "status": {"const": "ok"}, "matches": {"type": "array", "items": {"type": "string"}}, "cursor_start": {"type": "number"}, "cursor_end": {"type": "number"}, "metadata": {"type": "object"}, } } schema_fragments["history_request"] = { "properties": { "output": {"type": "boolean"}, "raw": {"type": "boolean"}, "hist_access_type": {"enum": ["range", "tail", "search"]}, "session": {"type": "number"}, "start": {"type": "number"}, "stop": {"type": "number"}, "n": {"type": "number"}, "pattern": {"type": "string"}, "unique": {"type": "boolean"}, }, "required": ["output", "raw", "hist_access_type"], } schema_fragments["history_reply"] = { "properties": { "status": {"const": "ok"}, "history": {"type": "array", "items": {"minItems": 3, "maxItems": 3}}, } } schema_fragments["is_complete_request"] = { "properties": { "code": {"type": "string"}, } } schema_fragments["is_complete_reply"] = { "properties": { "status": {"enum": ["complete", "incomplete", "invalid", "unknown"]}, "indent": {"type": "string"}, }, "required": ["status"], } # NB connect_request is deprecated schema_fragments["connect_request"] = {"properties": {}} schema_fragments["connect_reply"] = { "properties": { "shell_port": {"type": "number"}, "iopub_port": {"type": "number"}, "stdin_port": {"type": "number"}, "hb_port": {"type": "number"}, "control_port": {"type": "number"}, } } schema_fragments["comm_info_request"] = { "properties": { "target_name": {"type": "string"}, }, "required": [], } schema_fragments["comm_info_reply"] = { "properties": { # statuses 'error' and 'abort' change the structure, so check separately "status": {"const": "ok"}, "comms": {"type": "object"}, } } schema_fragments["kernel_info_request"] = {"properties": {}} schema_fragments["kernel_info_reply"] = { "properties": { # statuses 'error' and 'abort' change the structure, so check separately "status": {"const": "ok"}, "protocol_version": {"type": "string"}, "implementation": {"type": "string"}, "implementation_version": {"type": "string"}, "language_info": {"type": "object"}, "banner": {"type": "string"}, "debugger": {"type": "boolean"}, "help_links": { "type": "array", "items": { "type": "object", "properties": {"text": {"type": "string"}, "url": {"type": "string"}}, }, }, }, "required": ["status", "protocol_version", "implementation", "language_info", "banner"], } schema_fragments["shutdown_request"] = { "properties": { "restart": {"type": "boolean"}, } } schema_fragments["shutdown_reply"] = { "properties": { # statuses 'error' and 'abort' change the structure, so check separately "status": {"const": "ok"}, "restart": {"type": "boolean"}, } } schema_fragments["interrupt_request"] = {"properties": {}} schema_fragments["interrupt_reply"] = { "properties": { # statuses 'error' and 'abort' change the structure, so check separately "status": {"const": "ok"}, } } # IOPub messages ---------------------------------------------- mime_data = { "type": "object", "patternProperties": {r"^[\w\-\+\.]+/[\w\-\+\.]+$": {}}, "additionalProperties": False, } schema_fragments["stream"] = { "properties": { "name": {"enum": ["stdout", "stderr"]}, "text": {"type": "string"}, } } schema_fragments["display_data"] = { "properties": { "data": mime_data, "metadata": {"type": "object"}, "transient": {"type": "object"}, }, "required": ["data", "metadata"], } schema_fragments["update_display_data"] = { "properties": { "data": mime_data, "metadata": {"type": "object"}, "transient": {"type": "object"}, } } schema_fragments["execute_result"] = { "properties": { "execution_count": {"type": "number"}, "data": mime_data, "metadata": {"type": "object"}, "transient": {"type": "object"}, }, "required": ["execution_count", "data", "metadata"], } schema_fragments["clear_output"] = { "properties": { "wait": {"type": "boolean"}, } } schema_fragments["execute_input"] = { "properties": { "code": {"type": "string"}, "execution_count": {"type": "number"}, } } schema_fragments["error"] = { "properties": { "ename": {"type": "string"}, "evalue": {"type": "string"}, "traceback": {"type": "array", "items": {"type": "string"}}, } } schema_fragments["status"] = { "properties": { "execution_state": {"enum": ["busy", "idle", "starting"]}, } } # Stdin messages --------------------------------------------- schema_fragments["input_request"] = { "properties": { "prompt": {"type": "string"}, "password": {"type": "number"}, } } schema_fragments["input_reply"] = { "properties": { "value": {"type": "string"}, } } jupyter_kernel_test-0.7.0/pyproject.toml000066400000000000000000000051131457410417000205360ustar00rootroot00000000000000[build-system] requires = ["hatchling >=1.5"] build-backend = "hatchling.build" [project] name = "jupyter_kernel_test" license = { file = "LICENSE" } readme = "README.rst" classifiers = [ "License :: OSI Approved :: BSD License", "Intended Audience :: Developers", "Programming Language :: Python :: 3", "Topic :: Software Development :: Testing" ] requires-python = ">=3.8" dependencies = [ "jupyter_client >=6.1.13", "jsonschema" ] dynamic = ["description", "version"] [[project.authors]] name = "Jupyter Development Team" email = "jupyter@googlegroups.com" [project.urls] Homepage = "https://github.com/jupyter/jupyter_kernel_test" [project.optional-dependencies] test = [ "ipykernel", "pre-commit" ] [tool.hatch.version] path = "jupyter_kernel_test/__init__.py" [tool.hatch.envs.test] features = ["test"] [tool.hatch.envs.test.scripts] test = "python -m unittest -v {args}" [tool.hatch.envs.lint] detached = true dependencies = ["pre-commit"] [tool.hatch.envs.lint.scripts] build = [ "pre-commit run --all-files ruff", "pre-commit run --all-files ruff-format" ] [tool.hatch.envs.typing] dependencies = [ "pre-commit"] detached = true [tool.hatch.envs.typing.scripts] test = "pre-commit run --all-files --hook-stage manual mypy" [tool.mypy] files = "jupyter_kernel_test" python_version = "3.8" strict = true enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] warn_unreachable = true [tool.ruff] line-length = 100 [tool.ruff.lint] extend-select = [ "B", # flake8-bugbear "I", # isort "ARG", # flake8-unused-arguments "C4", # flake8-comprehensions #"EM", # flake8-errmsg "ICN", # flake8-import-conventions "G", # flake8-logging-format "PGH", # pygrep-hooks "PIE", # flake8-pie "PL", # pylint "PTH", # flake8-use-pathlib "PT", # flake8-pytest-style "RET", # flake8-return "RUF", # Ruff-specific "SIM", # flake8-simplify "T20", # flake8-print "UP", # pyupgrade "YTT", # flake8-2020 "EXE", # flake8-executable "PYI", # flake8-pyi "S", # flake8-bandit ] ignore = [ "PLR", # Design related pylint codes "RUF012", # Mutable class attributes should be annotated with "S101", # Use of `assert` detected "PT009" # Use a regular `assert` instead of unittest-style" ] unfixable = [ # Don't touch print statements "T201", # Don't touch noqa lines "RUF100", ] [tool.repo-review] ignore = ["PY004", "PY007","PP301", "PP308", "GH102", "RTD100"] jupyter_kernel_test-0.7.0/test_ipykernel.py000066400000000000000000000106501457410417000212370ustar00rootroot00000000000000""" Example use of jupyter_kernel_test, with tests for the default python3 kernel (IPyKernel). This includes all the currently available tests. """ import unittest import jupyter_kernel_test as jkt class IPyKernelTests(jkt.KernelTests): # REQUIRED # the kernel to be tested # this is the normally the name of the directory containing the # kernel.json file - you should be able to do # `jupyter console --kernel KERNEL_NAME` kernel_name = "python3" # Everything else is OPTIONAL # the name of the language the kernel executes # checked against language_info.name in kernel_info_reply language_name = "python" # the normal file extension (including the leading dot) for this language # checked against language_info.file_extension in kernel_info_reply file_extension = ".py" # code which should write the exact string `hello, world` to STDOUT code_hello_world = "print('hello, world')" # code which should cause (any) text to be written to STDERR code_stderr = "import sys; print('test', file=sys.stderr)" # samples for the autocompletion functionality # for each dictionary, `text` is the input to try and complete, and # `matches` the list of all complete matching strings which should be found completion_samples = [ { "text": "zi", "matches": {"zip"}, }, ] # samples for testing code-completeness (used by console only) # these samples should respectively be unambiguously complete statements # (which should be executed on ), incomplete statements or code # which should be identified as invalid complete_code_samples = ["1", "print('hello, world')", "def f(x):\n return x*2\n\n\n"] incomplete_code_samples = ["print('''hello", "def f(x):\n x*2"] invalid_code_samples = ["import = 7q"] # code which should cause a help pager to be displayed (as of 4.1, this is # displayed by the notebook only as inline text, so it's probably more # useful for console clients) code_page_something = "zip?" # code which should generate a (user-level) error in the kernel, and send # a traceback to the client code_generate_error = "raise" # a statement or block of code which generates a result (which is shown # as Out[n] instead of just something printed to stdout) # running each `code` should cause `result` to be displayed (note that the # result here will always be a string representation of whatever the actual # result type is - be careful of string formatting) code_execute_result = [ {"code": "1+2+3", "result": "6"}, {"code": "[n*n for n in range(1, 4)]", "result": "[1, 4, 9]"}, ] # code which generates some sort of rich output # for each `code` input a single rich display object with the specified # `mime` type should be sent to the frontend # note that this expects a `display_data` message rather than # `execute_result`; this test might be a little too inflexible in some cases code_display_data = [ { "code": "from IPython.display import HTML, display; display(HTML('test'))", "mime": "text/html", }, { "code": "from IPython.display import Math, display; display(Math('\\frac{1}{2}'))", "mime": "text/latex", }, ] # test the support for searching/recalling history (used by console only) # the history tests reuse the code blocks in `code_execute_result` above, # so will not run if no test code is available # `code_history_pattern` is a glob-style pattern which should match at least # one code sample in `code_execute_result` # `supported_history_operations` is a list of the `hist_access_type` options # which should be tested; possible values are "tail", "range" and "search" code_history_pattern = "1?2*" supported_history_operations = ("tail", "search") # test the support for object inspection # the sample should be a name about which the kernel can give some help # information (a built-in function is probably a good choice) # only the default inspection level (equivalent to ipython "obj?") # is currently tested code_inspect_sample = "zip" # a code sample which should cause a `clear_output` message to be sent to # the client code_clear_output = "from IPython.display import clear_output; clear_output()" if __name__ == "__main__": unittest.main() jupyter_kernel_test-0.7.0/test_irkernel.py000066400000000000000000000024051457410417000210470ustar00rootroot00000000000000""" A non-python example, with tests for IRKernel (irkernel.github.io). (Beware of python quoting/string escaping rules being different to the language being tested) """ import os import unittest from jupyter_client.kernelspec import NoSuchKernel import jupyter_kernel_test as jkt class IRKernelTests(jkt.KernelTests): kernel_name = "ir" @classmethod def setUpClass(cls): try: cls.km, cls.kc = jkt.start_new_kernel(kernel_name=cls.kernel_name) except NoSuchKernel: raise unittest.SkipTest("No ir kernel installed") from None language_name = "R" file_extension = ".r" code_hello_world = 'print("hello, world")' completion_samples = ( [ { "text": "zi", "matches": {"zip"}, }, ] if os.name != "nt" else [] ) # zip is not available on Windows complete_code_samples = ["1", "print('hello, world')", "f <- function(x) {x*2}"] incomplete_code_samples = ["print('hello", "f <- function(x) {x"] code_generate_error = "raise" code_display_data = [ {"code": "plot(iris)", "mime": "image/png"}, {"code": "1+2+3", "mime": "text/plain"}, ] if __name__ == "__main__": unittest.main() jupyter_kernel_test-0.7.0/test_xeus_cling.py000066400000000000000000000022121457410417000213700ustar00rootroot00000000000000""" A non-python example, with tests for xeus-cling kernel (https://github.com/jupyter-xeus/xeus-cling). (Beware of python quoting/string escaping rules being different to the language being tested) """ import unittest from jupyter_client.kernelspec import NoSuchKernel import jupyter_kernel_test as jkt class XeusClingKernelTests(jkt.KernelTests): kernel_name = "xcpp17" @classmethod def setUpClass(cls): try: cls.km, cls.kc = jkt.start_new_kernel(kernel_name=cls.kernel_name) except NoSuchKernel: raise unittest.SkipTest("Xeus-Cling Kernel not installed") from None language_name = "c++" file_extension = ".cpp" code_hello_world = '#include \nstd::cout << "hello, world!" << std::endl;' code_stderr = '#include \nstd::cerr << "some error" << std::endl;' complete_code_samples = ["1", "int j=5"] incomplete_code_samples = ["double sqr(double a"] code_generate_error = 'throw std::runtime_error("Unknown exception");' code_execute_result = [ {"code": "int j = 5;j", "result": "5"}, ] if __name__ == "__main__": unittest.main()