diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index baa1327..f6adebc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,42 +2,35 @@ default_language_version: python: python3.8 repos: - - repo: https://github.com/psf/black - rev: 23.3.0 + - repo: local hooks: - - id: black - - - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 - hooks: - - id: flake8 - additional_dependencies: - - "flake8-builtins" - - "flake8-implicit-str-concat" - - "flake8-no-pep420" - - - repo: https://github.com/PyCQA/isort - rev: 5.12.0 - hooks: - - id: isort - - - repo: https://github.com/sqlfluff/sqlfluff - rev: 2.0.3 - # This hook filters sql files, so if there aren't sql files in the staging - # area, then `pre-commit run` will skip it. Indeed, `pre-commit run - # --all-files` will skip it too, as the `--all-files` argument doesn't work - # as documented. - hooks: - - id: sqlfluff-fix + - id: black + name: black + entry: just black + language: system + types: [python] + require_serial: true + - id: ruff + name: ruff + entry: just ruff + language: system + types: [python] + require_serial: true + - id: sqlfluff + name: sqlfluff + entry: just sqlfluff + language: system + types: [python] + require_serial: true - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.1.0 hooks: - - id: trailing-whitespace - - id: end-of-file-fixer - - id: debug-statements - - id: check-ast - - id: check-json - - id: check-toml - - id: check-yaml - - id: detect-private-key + - id: trailing-whitespace + - id: end-of-file-fixer + - id: debug-statements + - id: check-ast + - id: check-json + - id: check-toml + - id: check-yaml + - id: detect-private-key diff --git a/justfile b/justfile index 359a7e2..2e1f96d 100644 --- a/justfile +++ b/justfile @@ -1,6 +1,4 @@ -# just has no idiom for setting a default value for an environment variable -# so we shell out, as we need VIRTUAL_ENV in the justfile environment -export VIRTUAL_ENV := `echo ${VIRTUAL_ENV:-.venv}` +export VIRTUAL_ENV := env_var_or_default("VIRTUAL_ENV", ".venv") export BIN := VIRTUAL_ENV + if os_family() == "unix" { "/bin" } else { "/Scripts" } export PIP := BIN + if os_family() == "unix" { "/python -m pip" } else { "/python.exe -m pip" } @@ -21,6 +19,8 @@ clean: # ensure valid virtualenv virtualenv: #!/usr/bin/env bash + set -euo pipefail + # allow users to specify python version in .env PYTHON_VERSION=${PYTHON_VERSION:-$DEFAULT_PYTHON} @@ -33,6 +33,8 @@ virtualenv: _compile src dst *args: virtualenv #!/usr/bin/env bash + set -euo pipefail + # exit if src file is older than dst file (-nt = 'newer than', but we negate with || to avoid error exit code) test "${FORCE:-}" = "true" -o {{ src }} -nt {{ dst }} || exit 0 $BIN/pip-compile --allow-unsafe --generate-hashes --output-file={{ dst }} {{ src }} {{ args }} @@ -51,6 +53,8 @@ requirements-dev *args: requirements-prod # ensure prod requirements installed and up to date prodenv: requirements-prod #!/usr/bin/env bash + set -euo pipefail + # exit if .txt file has not changed since we installed them (-nt == "newer than', but we negate with || to avoid error exit code) test requirements.prod.txt -nt $VIRTUAL_ENV/.prod || exit 0 @@ -64,6 +68,8 @@ prodenv: requirements-prod # ensure dev requirements installed and up to date devenv: prodenv requirements-dev && install-precommit #!/usr/bin/env bash + set -euo pipefail + # exit if .txt file has not changed since we installed them (-nt == "newer than', but we negate with || to avoid error exit code) test requirements.dev.txt -nt $VIRTUAL_ENV/.dev || exit 0 @@ -74,6 +80,8 @@ devenv: prodenv requirements-dev && install-precommit # ensure precommit is installed install-precommit: #!/usr/bin/env bash + set -euo pipefail + BASE_DIR=$(git rev-parse --show-toplevel) test -f $BASE_DIR/.git/hooks/pre-commit || $BIN/pre-commit install @@ -81,32 +89,39 @@ install-precommit: # upgrade dev or prod dependencies (specify package to upgrade single package, all by default) upgrade env package="": virtualenv #!/usr/bin/env bash + set -euo pipefail + opts="--upgrade" test -z "{{ package }}" || opts="--upgrade-package {{ package }}" FORCE=true "{{ just_executable() }}" requirements-{{ env }} $opts -# *ARGS is variadic, 0 or more. This allows us to do `just test -k match`, for example. +# *args is variadic, 0 or more. This allows us to do `just test -k match`, for example. # Run the tests -test *ARGS: devenv - $BIN/opensafely exec python -m pytest --disable-warnings {{ ARGS }} +test *args: devenv + $BIN/opensafely exec python -m pytest --disable-warnings {{ args }} + + +black *args=".": devenv + $BIN/black --check {{ args }} + +ruff *args=".": devenv + $BIN/ruff check {{ args }} +sqlfluff *args=".": devenv + $BIN/sqlfluff lint {{ args }} -# runs the format (black), sort (isort) and lint (flake8) check but does not change any files -check: devenv - $BIN/black --check . - $BIN/isort --check-only --diff . - $BIN/flake8 - $BIN/sqlfluff lint . +# run the various dev checks but does not change any files +check: black ruff sqlfluff # fix formatting and import sort ordering fix: devenv $BIN/black . - $BIN/isort . + $BIN/ruff --fix . $BIN/sqlfluff fix . # Run JupyterLab -run *ARGS: devenv - opensafely jupyter {{ ARGS }} +run *args: devenv + opensafely jupyter {{ args }} diff --git a/requirements.dev.in b/requirements.dev.in index ae297c5..8f6ff3d 100644 --- a/requirements.dev.in +++ b/requirements.dev.in @@ -5,12 +5,8 @@ # pip-compile --generate-hashes --output-file=requirements.dev.txt requirements.dev.in black -flake8 -flake8-builtins -flake8-implicit-str-concat -flake8-no-pep420 -isort opensafely pip-tools pre-commit +ruff sqlfluff diff --git a/requirements.dev.txt b/requirements.dev.txt index f0208c9..cfea2fd 100644 --- a/requirements.dev.txt +++ b/requirements.dev.txt @@ -73,25 +73,6 @@ filelock==3.10.7 \ --hash=sha256:892be14aa8efc01673b5ed6589dbccb95f9a8596f0507e232626155495c18105 \ --hash=sha256:bde48477b15fde2c7e5a0713cbe72721cb5a5ad32ee0b8f419907960b9d75536 # via virtualenv -flake8==6.1.0 \ - --hash=sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23 \ - --hash=sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5 - # via - # -r requirements.dev.in - # flake8-builtins - # flake8-no-pep420 -flake8-builtins==2.2.0 \ - --hash=sha256:392d5af3a0720c5a863aa93dc47f48c879081345a143fe9f20d995fe9ff5686a \ - --hash=sha256:7ee5766d9c60e5d579dfda84e65c6d0e6c26005f6f59cb9bf722462d7987a807 - # via -r requirements.dev.in -flake8-implicit-str-concat==0.4.0 \ - --hash=sha256:b6acf233afee943dc1802ef4bc242a19f0419fac9943739e235d3f2aaf616361 \ - --hash=sha256:b91805a3e0ff30ae2890830548478af25c79a4a579ec402a6ba3538043dff60c - # via -r requirements.dev.in -flake8-no-pep420==2.7.0 \ - --hash=sha256:018bbe0fba039444689d02a0857310b62b90ff9bf737aff27e0b847ec7eb9ba3 \ - --hash=sha256:a1b6db4de355b87f8189714e68785a7c6a2d61d94f3e937b6cee336953f7d703 - # via -r requirements.dev.in identify==2.5.22 \ --hash=sha256:f0faad595a4687053669c112004178149f6c326db71ee999ae4636685753ad2f \ --hash=sha256:f7a93d6cf98e29bd07663c60728e7a4057615068d7a639d132dc883b2d54d31e @@ -104,10 +85,6 @@ iniconfig==2.0.0 \ --hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \ --hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374 # via pytest -isort==5.13.2 \ - --hash=sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109 \ - --hash=sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6 - # via -r requirements.dev.in jinja2==3.1.2 \ --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 @@ -166,14 +143,6 @@ markupsafe==2.1.2 \ --hash=sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6 \ --hash=sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58 # via jinja2 -mccabe==0.7.0 \ - --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \ - --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e - # via flake8 -more-itertools==9.1.0 \ - --hash=sha256:cabaa341ad0389ea83c17a94566a53ae4c9d07349861ecb14dc6d0345cf9ac5d \ - --hash=sha256:d2bc7f02446e86a68911e58ded76d6561eea00cddfb2a91e7019bbb586c799f3 - # via flake8-implicit-str-concat mypy-extensions==1.0.0 \ --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \ --hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782 @@ -219,14 +188,6 @@ pre-commit==3.5.0 \ --hash=sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32 \ --hash=sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660 # via -r requirements.dev.in -pycodestyle==2.11.0 \ - --hash=sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0 \ - --hash=sha256:5d1013ba8dc7895b548be5afb05740ca82454fd899971563d2ef625d090326f8 - # via flake8 -pyflakes==3.1.0 \ - --hash=sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774 \ - --hash=sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc - # via flake8 pygments==2.14.0 \ --hash=sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297 \ --hash=sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717 @@ -345,6 +306,25 @@ regex==2023.3.23 \ --hash=sha256:fdf7ad455f1916b8ea5cdbc482d379f6daf93f3867b4232d14699867a5a13af7 \ --hash=sha256:fffe57312a358be6ec6baeb43d253c36e5790e436b7bf5b7a38df360363e88e9 # via sqlfluff +ruff==0.1.8 \ + --hash=sha256:05ffe9dbd278965271252704eddb97b4384bf58b971054d517decfbf8c523f05 \ + --hash=sha256:5daaeaf00ae3c1efec9742ff294b06c3a2a9db8d3db51ee4851c12ad385cda30 \ + --hash=sha256:7d076717c67b34c162da7c1a5bda16ffc205e0e0072c03745275e7eab888719f \ + --hash=sha256:7de792582f6e490ae6aef36a58d85df9f7a0cfd1b0d4fe6b4fb51803a3ac96fa \ + --hash=sha256:a05b0ddd7ea25495e4115a43125e8a7ebed0aa043c3d432de7e7d6e8e8cd6448 \ + --hash=sha256:aa8ee4f8440023b0a6c3707f76cadce8657553655dcbb5fc9b2f9bb9bee389f6 \ + --hash=sha256:b6a21ab023124eafb7cef6d038f835cb1155cd5ea798edd8d9eb2f8b84be07d9 \ + --hash=sha256:bd8ee69b02e7bdefe1e5da2d5b6eaaddcf4f90859f00281b2333c0e3a0cc9cd6 \ + --hash=sha256:c8e3255afd186c142eef4ec400d7826134f028a85da2146102a1172ecc7c3696 \ + --hash=sha256:ce697c463458555027dfb194cb96d26608abab920fa85213deb5edf26e026664 \ + --hash=sha256:db6cedd9ffed55548ab313ad718bc34582d394e27a7875b4b952c2d29c001b26 \ + --hash=sha256:e49fbdfe257fa41e5c9e13c79b9e79a23a79bd0e40b9314bc53840f520c2c0b3 \ + --hash=sha256:e6f08ca730f4dc1b76b473bdf30b1b37d42da379202a059eae54ec7fc1fbcfed \ + --hash=sha256:f35960b02df6b827c1b903091bb14f4b003f6cf102705efc4ce78132a0aa5af3 \ + --hash=sha256:f41f692f1691ad87f51708b823af4bb2c5c87c9248ddd3191c8f088e66ce590a \ + --hash=sha256:f7ee467677467526cfe135eab86a40a0e8db43117936ac4f9b469ce9cdb3fb62 \ + --hash=sha256:ff78a7583020da124dd0deb835ece1d87bb91762d40c514ee9b67a087940528b + # via -r requirements.dev.in sqlfluff==2.3.5 \ --hash=sha256:2ca095a2f2cced5573a83fc8a6d2aceb36edd21a8c4c5d8099b6544e386d86a1 \ --hash=sha256:fd77ef5a41ebfa798235a5b28bcfa71f7521e9336159a08b40b545953e84c3c3