mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-24 18:44:00 +03:00
Lint with pre-commit (#7900)
Following [my comment here](https://github.com/encode/django-rest-framework/pull/7589#issuecomment-813301322) and [Django's own move to pre-commit](https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/coding-style/#pre-commit-checks). * Add pre-commit config file to run flake8 and isort. * Add extra "common sense" hooks. * Run pre-commit on GitHub actions using the [official action](https://github.com/pre-commit/action/). This is a good way to get up-and-running but it would be better if we activated [pre-commit.ci](https://pre-commit.ci/), which is faster and will auto-update the hooks for us going forwards. * Remove `runtests.py` code for running linting tools. * Remove `runtests.py --fast` flag, since that would now just run `pytest -q`, which can be done with `runtests.py -q` instead. * Remove tox configuration and requirements files for linting. * Update the contributing guide to mention setting up pre-commit.
This commit is contained in:
parent
846fe70cff
commit
aa12a5f967
24
.github/workflows/pre-commit.yml
vendored
Normal file
24
.github/workflows/pre-commit.yml
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
name: pre-commit
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pre-commit:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: 3.9
|
||||||
|
|
||||||
|
- uses: pre-commit/action@v2.0.0
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -15,6 +15,7 @@
|
||||||
MANIFEST
|
MANIFEST
|
||||||
coverage.*
|
coverage.*
|
||||||
|
|
||||||
|
!.github
|
||||||
!.gitignore
|
!.gitignore
|
||||||
|
!.pre-commit-config.yaml
|
||||||
!.travis.yml
|
!.travis.yml
|
||||||
!.isort.cfg
|
|
||||||
|
|
20
.pre-commit-config.yaml
Normal file
20
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v3.4.0
|
||||||
|
hooks:
|
||||||
|
- id: check-added-large-files
|
||||||
|
- id: check-case-conflict
|
||||||
|
- id: check-json
|
||||||
|
- id: check-merge-conflict
|
||||||
|
- id: check-symlinks
|
||||||
|
- id: check-toml
|
||||||
|
- repo: https://github.com/pycqa/isort
|
||||||
|
rev: 5.8.0
|
||||||
|
hooks:
|
||||||
|
- id: isort
|
||||||
|
- repo: https://gitlab.com/pycqa/flake8
|
||||||
|
rev: 3.9.0
|
||||||
|
hooks:
|
||||||
|
- id: flake8
|
||||||
|
additional_dependencies:
|
||||||
|
- flake8-tidy-imports
|
|
@ -27,7 +27,6 @@ matrix:
|
||||||
- { python: "3.9", env: DJANGO=main }
|
- { python: "3.9", env: DJANGO=main }
|
||||||
|
|
||||||
- { python: "3.8", env: TOXENV=base }
|
- { python: "3.8", env: TOXENV=base }
|
||||||
- { python: "3.8", env: TOXENV=lint }
|
|
||||||
- { python: "3.8", env: TOXENV=docs }
|
- { python: "3.8", env: TOXENV=docs }
|
||||||
|
|
||||||
- python: "3.8"
|
- python: "3.8"
|
||||||
|
|
|
@ -54,11 +54,19 @@ To start developing on Django REST framework, first create a Fork from the
|
||||||
Then clone your fork. The clone command will look like this, with your GitHub
|
Then clone your fork. The clone command will look like this, with your GitHub
|
||||||
username instead of YOUR-USERNAME:
|
username instead of YOUR-USERNAME:
|
||||||
|
|
||||||
git clone https://github.com/YOUR-USERNAME/Spoon-Knife
|
git clone https://github.com/YOUR-USERNAME/django-rest-framework
|
||||||
|
|
||||||
See GitHub's [_Fork a Repo_][how-to-fork] Guide for more help.
|
See GitHub's [_Fork a Repo_][how-to-fork] Guide for more help.
|
||||||
|
|
||||||
Changes should broadly follow the [PEP 8][pep-8] style conventions, and we recommend you set up your editor to automatically indicate non-conforming styles.
|
Changes should broadly follow the [PEP 8][pep-8] style conventions, and we recommend you set up your editor to automatically indicate non-conforming styles.
|
||||||
|
You can check your contributions against these conventions each time you commit using the [pre-commit](https://pre-commit.com/) hooks, which we also run on CI.
|
||||||
|
To set them up, first ensure you have the pre-commit tool installed, for example:
|
||||||
|
|
||||||
|
python -m pip install pre-commit
|
||||||
|
|
||||||
|
Then run:
|
||||||
|
|
||||||
|
pre-commit install
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
|
@ -79,18 +87,6 @@ Run using a more concise output style.
|
||||||
|
|
||||||
./runtests.py -q
|
./runtests.py -q
|
||||||
|
|
||||||
Run the tests using a more concise output style, no coverage, no flake8.
|
|
||||||
|
|
||||||
./runtests.py --fast
|
|
||||||
|
|
||||||
Don't run the flake8 code linting.
|
|
||||||
|
|
||||||
./runtests.py --nolint
|
|
||||||
|
|
||||||
Only run the flake8 code linting, don't run the tests.
|
|
||||||
|
|
||||||
./runtests.py --lintonly
|
|
||||||
|
|
||||||
Run the tests for a given test case.
|
Run the tests for a given test case.
|
||||||
|
|
||||||
./runtests.py MyTestCase
|
./runtests.py MyTestCase
|
||||||
|
|
|
@ -9,5 +9,4 @@
|
||||||
-r requirements/requirements-optionals.txt
|
-r requirements/requirements-optionals.txt
|
||||||
-r requirements/requirements-testing.txt
|
-r requirements/requirements-testing.txt
|
||||||
-r requirements/requirements-documentation.txt
|
-r requirements/requirements-documentation.txt
|
||||||
-r requirements/requirements-codestyle.txt
|
|
||||||
-r requirements/requirements-packaging.txt
|
-r requirements/requirements-packaging.txt
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
# PEP8 code linting, which we run on all commits.
|
|
||||||
flake8>=3.8.4,<3.9
|
|
||||||
flake8-tidy-imports>=4.1.0,<4.2
|
|
||||||
|
|
||||||
# Sort and lint imports
|
|
||||||
isort>=5.6.2,<6.0
|
|
70
runtests.py
70
runtests.py
|
@ -1,42 +1,8 @@
|
||||||
#! /usr/bin/env python3
|
#! /usr/bin/env python3
|
||||||
import subprocess
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
PYTEST_ARGS = {
|
|
||||||
'default': [],
|
|
||||||
'fast': ['-q'],
|
|
||||||
}
|
|
||||||
|
|
||||||
FLAKE8_ARGS = ['rest_framework', 'tests']
|
|
||||||
|
|
||||||
ISORT_ARGS = ['--check-only', '--diff', 'rest_framework', 'tests']
|
|
||||||
|
|
||||||
|
|
||||||
def exit_on_failure(ret, message=None):
|
|
||||||
if ret:
|
|
||||||
sys.exit(ret)
|
|
||||||
|
|
||||||
|
|
||||||
def flake8_main(args):
|
|
||||||
print('Running flake8 code linting')
|
|
||||||
ret = subprocess.call(['flake8'] + args)
|
|
||||||
print('flake8 failed' if ret else 'flake8 passed')
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def isort_main(args):
|
|
||||||
print('Running isort code checking')
|
|
||||||
ret = subprocess.call(['isort'] + args)
|
|
||||||
|
|
||||||
if ret:
|
|
||||||
print('isort failed: Some modules have incorrectly ordered imports. Fix by running `isort --recursive .`')
|
|
||||||
else:
|
|
||||||
print('isort passed')
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def split_class_and_function(string):
|
def split_class_and_function(string):
|
||||||
class_string, function_string = string.split('.', 1)
|
class_string, function_string = string.split('.', 1)
|
||||||
|
@ -54,31 +20,6 @@ def is_class(string):
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
try:
|
|
||||||
sys.argv.remove('--nolint')
|
|
||||||
except ValueError:
|
|
||||||
run_flake8 = True
|
|
||||||
run_isort = True
|
|
||||||
else:
|
|
||||||
run_flake8 = False
|
|
||||||
run_isort = False
|
|
||||||
|
|
||||||
try:
|
|
||||||
sys.argv.remove('--lintonly')
|
|
||||||
except ValueError:
|
|
||||||
run_tests = True
|
|
||||||
else:
|
|
||||||
run_tests = False
|
|
||||||
|
|
||||||
try:
|
|
||||||
sys.argv.remove('--fast')
|
|
||||||
except ValueError:
|
|
||||||
style = 'default'
|
|
||||||
else:
|
|
||||||
style = 'fast'
|
|
||||||
run_flake8 = False
|
|
||||||
run_isort = False
|
|
||||||
|
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
pytest_args = sys.argv[1:]
|
pytest_args = sys.argv[1:]
|
||||||
first_arg = pytest_args[0]
|
first_arg = pytest_args[0]
|
||||||
|
@ -104,14 +45,5 @@ if __name__ == "__main__":
|
||||||
# `runtests.py TestCase [flags]`
|
# `runtests.py TestCase [flags]`
|
||||||
# `runtests.py test_function [flags]`
|
# `runtests.py test_function [flags]`
|
||||||
pytest_args = ['tests', '-k', pytest_args[0]] + pytest_args[1:]
|
pytest_args = ['tests', '-k', pytest_args[0]] + pytest_args[1:]
|
||||||
else:
|
|
||||||
pytest_args = PYTEST_ARGS[style]
|
|
||||||
|
|
||||||
if run_tests:
|
sys.exit(pytest.main(pytest_args))
|
||||||
exit_on_failure(pytest.main(pytest_args))
|
|
||||||
|
|
||||||
if run_flake8:
|
|
||||||
exit_on_failure(flake8_main(FLAKE8_ARGS))
|
|
||||||
|
|
||||||
if run_isort:
|
|
||||||
exit_on_failure(isort_main(ISORT_ARGS))
|
|
||||||
|
|
12
tox.ini
12
tox.ini
|
@ -5,7 +5,7 @@ envlist =
|
||||||
{py36,py37,py38,py39}-django31,
|
{py36,py37,py38,py39}-django31,
|
||||||
{py36,py37,py38,py39}-django32,
|
{py36,py37,py38,py39}-django32,
|
||||||
{py38,py39}-djangomain,
|
{py38,py39}-djangomain,
|
||||||
base,dist,lint,docs,
|
base,dist,docs,
|
||||||
|
|
||||||
[travis:env]
|
[travis:env]
|
||||||
DJANGO =
|
DJANGO =
|
||||||
|
@ -16,7 +16,7 @@ DJANGO =
|
||||||
main: djangomain
|
main: djangomain
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
commands = python -W error::DeprecationWarning -W error::PendingDeprecationWarning runtests.py --fast --coverage {posargs}
|
commands = python -W error::DeprecationWarning -W error::PendingDeprecationWarning runtests.py --coverage {posargs}
|
||||||
envdir = {toxworkdir}/venvs/{envname}
|
envdir = {toxworkdir}/venvs/{envname}
|
||||||
setenv =
|
setenv =
|
||||||
PYTHONDONTWRITEBYTECODE=1
|
PYTHONDONTWRITEBYTECODE=1
|
||||||
|
@ -37,18 +37,12 @@ deps =
|
||||||
-rrequirements/requirements-testing.txt
|
-rrequirements/requirements-testing.txt
|
||||||
|
|
||||||
[testenv:dist]
|
[testenv:dist]
|
||||||
commands = ./runtests.py --fast --no-pkgroot --staticfiles {posargs}
|
commands = ./runtests.py --no-pkgroot --staticfiles {posargs}
|
||||||
deps =
|
deps =
|
||||||
django
|
django
|
||||||
-rrequirements/requirements-testing.txt
|
-rrequirements/requirements-testing.txt
|
||||||
-rrequirements/requirements-optionals.txt
|
-rrequirements/requirements-optionals.txt
|
||||||
|
|
||||||
[testenv:lint]
|
|
||||||
commands = ./runtests.py --lintonly
|
|
||||||
deps =
|
|
||||||
-rrequirements/requirements-codestyle.txt
|
|
||||||
-rrequirements/requirements-testing.txt
|
|
||||||
|
|
||||||
[testenv:docs]
|
[testenv:docs]
|
||||||
skip_install = true
|
skip_install = true
|
||||||
commands = mkdocs build
|
commands = mkdocs build
|
||||||
|
|
Loading…
Reference in New Issue
Block a user