From f757ad79dc2f0ccc8da32d7f2aa43523ff80d51a Mon Sep 17 00:00:00 2001 From: Teo Zosa Date: Tue, 11 May 2021 14:32:53 -0700 Subject: [PATCH 1/6] :art: Simplify last exit code command formatting --- {{cookiecutter.project_slug}}/tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/tox.ini b/{{cookiecutter.project_slug}}/tox.ini index ace1d565b..ba9d15116 100644 --- a/{{cookiecutter.project_slug}}/tox.ini +++ b/{{cookiecutter.project_slug}}/tox.ini @@ -83,7 +83,7 @@ commands = --paths-to-mutate={{cookiecutter.package_name}}/ \ --runner="{[testenv]commands}" \ --tests-dir=tests/ || \ - MUTMUT_EXIT_CODE="$\{?\}"; \ + MUTMUT_EXIT_CODE=$?; \ if [[ "$\{MUTMUT_EXIT_CODE\}" -eq 1 ]]; \ then \ exit "$\{MUTMUT_EXIT_CODE\}"; \ From 6bf02e767ac5aadcfec86d0d508afe7b736b8e7c Mon Sep 17 00:00:00 2001 From: Teo Zosa Date: Wed, 12 May 2021 19:10:40 -0700 Subject: [PATCH 2/6] :bento: Add `example.ipynb` --- .../example.ipynb | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 {{cookiecutter.project_slug}}/{{cookiecutter.package_name}}/example.ipynb diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.package_name}}/example.ipynb b/{{cookiecutter.project_slug}}/{{cookiecutter.package_name}}/example.ipynb new file mode 100644 index 000000000..b06f4344e --- /dev/null +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.package_name}}/example.ipynb @@ -0,0 +1,106 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "outputs": [], + "source": [ + "import operator" + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + } + }, + { + "cell_type": "code", + "execution_count": 2, + "outputs": [], + "source": [ + "def my_sum(nums: list[int]) -> int:\n", + " \"\"\"Returns the sum of a given list of integers\n", + "\n", + " Without using the `+` operator\n", + "\n", + " Args:\n", + " nums:\n", + "\n", + " Examples:\n", + " >>> my_sum([1, 1])\n", + " 2\n", + " >>> my_sum([])\n", + " 0\n", + "\n", + " \"\"\"\n", + " running_sum = 0\n", + " for num in nums:\n", + " running_sum = operator.add(running_sum, num)\n", + " return running_sum" + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + } + }, + { + "cell_type": "code", + "execution_count": 3, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 + 1 + 1 + 1 = 4\n" + ] + } + ], + "source": [ + "test_nums = [1] * 4\n", + "print(f\"{' + '.join(str(x) for x in test_nums)} = {my_sum(test_nums)}\")" + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + } + }, + { + "cell_type": "code", + "execution_count": 3, + "outputs": [], + "source": [], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + } + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file From b5ff37bdd537dfd291ed02beedfff27dff7741ab Mon Sep 17 00:00:00 2001 From: Teo Zosa Date: Wed, 12 May 2021 19:12:55 -0700 Subject: [PATCH 3/6] :heavy_plus_sign: Add `nbqa` dev dependency --- {{cookiecutter.project_slug}}/pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/{{cookiecutter.project_slug}}/pyproject.toml b/{{cookiecutter.project_slug}}/pyproject.toml index 335ada87d..169de917e 100644 --- a/{{cookiecutter.project_slug}}/pyproject.toml +++ b/{{cookiecutter.project_slug}}/pyproject.toml @@ -48,6 +48,7 @@ typer-cli = { version = "^0.0.11", optional = true} [tool.poetry.dev-dependencies] # Testing +nbqa = "^0.8.0" pytest = "^6.2.1" pytest-benchmark = {extras = ["histogram"], version = "^3.4.1"} pytest-cov = "^2.10.1" From 4449878db158e1498378d67c9fc6c640b3f63dec Mon Sep 17 00:00:00 2001 From: Teo Zosa Date: Wed, 12 May 2021 19:31:06 -0700 Subject: [PATCH 4/6] :green_heart: Exclude notebooks from `flakehell` `pre-commit` hook --- {{cookiecutter.project_slug}}/.pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/{{cookiecutter.project_slug}}/.pre-commit-config.yaml b/{{cookiecutter.project_slug}}/.pre-commit-config.yaml index 3310fcabc..27aedb1a5 100644 --- a/{{cookiecutter.project_slug}}/.pre-commit-config.yaml +++ b/{{cookiecutter.project_slug}}/.pre-commit-config.yaml @@ -35,6 +35,7 @@ repos: rev: v.0.8.0 hooks: - id: flakehell + exclude_types: [jupyter] # Docstring coverage tool - repo: https://github.com/econchick/interrogate From efd466dad4fed8470e092d91cb3f8513a461c7ea Mon Sep 17 00:00:00 2001 From: Teo Zosa Date: Wed, 12 May 2021 19:32:42 -0700 Subject: [PATCH 5/6] :construction_worker: Add `nbqa` pre-commit hooks --- .../.pre-commit-config.yaml | 53 +++++++++++++++++++ {{cookiecutter.project_slug}}/tox.ini | 2 + 2 files changed, 55 insertions(+) diff --git a/{{cookiecutter.project_slug}}/.pre-commit-config.yaml b/{{cookiecutter.project_slug}}/.pre-commit-config.yaml index 27aedb1a5..f55b083ea 100644 --- a/{{cookiecutter.project_slug}}/.pre-commit-config.yaml +++ b/{{cookiecutter.project_slug}}/.pre-commit-config.yaml @@ -66,6 +66,59 @@ repos: args: [--cache-dir=/dev/null, --config-file=tox.ini] types: [python] + - repo: https://github.com/nbQA-dev/nbQA + rev: 0.8.0 + hooks: + - id: nbqa-black + args: [--nbqa-mutate] + additional_dependencies: [black==21.5b0] + - id: nbqa-isort + args: [--nbqa-mutate] + additional_dependencies: [isort==5.8.0] + - id: nbqa-pyupgrade + args: [--nbqa-mutate] + additional_dependencies: [pyupgrade==v2.14.0] + + - repo: local + hooks: + - id: nbqa-bandit + name: nbqa-bandit + description: "Run tox env `bandit` on a Jupyter Notebook" + entry: .tox/precommit/bin/nbqa bandit + language: system + types: [jupyter] + + ## Override nbqa pre-packaged hooks to preempt spurious "Module not found" + ## errors + + # See: https://mypy.readthedocs.io/en/latest/running_mypy.html#missing-imports + - repo: local + hooks: + - id: nbqa-mypy + name: nbqa-mypy + description: "Run tox env `mypy` on a Jupyter Notebook" + entry: .tox/precommit/bin/nbqa mypy + # yamllint disable-line rule:line-length + args: [--cache-dir=/dev/null, --config-file=tox.ini] + language: system + types: [jupyter] + + # Note: submit docs for this to nbqa? + # ex. https://nbqa.readthedocs.io/en/latest/pre-commit.html + # referencing: + # yamllint disable-line rule:line-length + # [Remove pylint config E0401 and make pylint a local pre-commit hook #229](https://github.com/nbQA-dev/nbQA/pull/229/files) + + # E0401: import-error + - repo: local + hooks: + - id: nbqa-pylint + name: nbqa-pylint + description: "Run tox env `pylint` on a Jupyter Notebook" + entry: .tox/precommit/bin/nbqa pylint + language: system + types: [jupyter] + - repo: local hooks: - id: pylint diff --git a/{{cookiecutter.project_slug}}/tox.ini b/{{cookiecutter.project_slug}}/tox.ini index ba9d15116..cd3414188 100644 --- a/{{cookiecutter.project_slug}}/tox.ini +++ b/{{cookiecutter.project_slug}}/tox.ini @@ -137,11 +137,13 @@ parallel_show_output = {[testenv]parallel_show_output} [testenv:precommit] description = Run `pre-commit` hooks to auto-format and lint the codebase deps = + bandit # `nbqa-bandit` pre-commit hypothesis icontract icontract_hypothesis mypy + nbqa pylint pytest sphinx From c8d19eef05645b2b00c52a52585f21428df56cfb Mon Sep 17 00:00:00 2001 From: Teo Zosa Date: Wed, 12 May 2021 19:33:10 -0700 Subject: [PATCH 6/6] :white_check_mark: Add `nbqaxdoctest` tox testenv --- {{cookiecutter.project_slug}}/tox.ini | 29 ++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/{{cookiecutter.project_slug}}/tox.ini b/{{cookiecutter.project_slug}}/tox.ini index cd3414188..57a393708 100644 --- a/{{cookiecutter.project_slug}}/tox.ini +++ b/{{cookiecutter.project_slug}}/tox.ini @@ -1,8 +1,8 @@ [gh-actions] python = - 3.7: py37 - 3.8: py38 - 3.9: py39, coverage + 3.7: py37, nbqaxdoctest + 3.8: py38, nbqaxdoctest + 3.9: py39, coverage, nbqaxdoctest [tox] skip_missing_interpreters = true @@ -10,6 +10,7 @@ isolated_build = true envlist = py3{7,8,9}, coverage, + nbqaxdoctest, package [testenv] @@ -134,6 +135,28 @@ depends = py3{7,8,9} parallel_show_output = {[testenv]parallel_show_output} +[testenv:nbqaxdoctest] +description = Run notebook doctests directly via `xdoctest` (more efficient and + less error-prone than using the built-in `doctest` library or + running `xdoctest` via the `pytest` plugin). Note: if any test + fails, the test environment command fails with the FIRST non-zero + exit code encountered in the output job log. +deps = -r requirements-dev.txt +allowlist_externals = bash +commands = + bash -c '\ + find {toxinidir}/{{cookiecutter.package_name}} -type f -name "*.ipynb" \ + | parallel --joblog {toxworkdir}/{envname}.log -j 0 -k nbqa xdoctest \{\} --colored true; \ + NUM_FAILED_JOBS=$?; \ + echo "*****************$NUM_FAILED_JOBS FAILED JOBS*****************"; \ + cat {toxworkdir}/{envname}.log| awk "\$7 != 0"; \ + FAILURE_EXIT_CODES=$(cat {toxworkdir}/{envname}.log | awk "NR>1 && \$7 != 0 \{print \$7 \}") && \ + exit $\{FAILURE_EXIT_CODES:0:1\}' +# Run after testenv since auto-generated temp `.py` files interfere with pytest +depends = + py3{7,8,9} +parallel_show_output = {[testenv]parallel_show_output} + [testenv:precommit] description = Run `pre-commit` hooks to auto-format and lint the codebase deps =