Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save kevinbowen777/464e682b1d78ca402ba131aabf02360a to your computer and use it in GitHub Desktop.
Save kevinbowen777/464e682b1d78ca402ba131aabf02360a to your computer and use it in GitHub Desktop.
A guide for migrating Django projects using flake8 to ruff

Installing & configuring ruff

Summary:

The purpose of this document is to outline a migration guide for Django projects using poetry and nox to migrate from using flake8 to ruff for the purposes of linting the project.

created: 20230502 updated: 20230510 updated: 20230513

The purpose of this document is to outline the steps necessary to migrate a Django web application's linting infrastructure from flake8 to ruff.

Migration Outline

1. Replace flake8 with ruff
2. Install ruff & initial config in pyproject.toml
3. Update nox lint session with ruff. Remove flake8 packages
4. Migrate project identifier fields from setup.cfg to pyproject.toml
5. Add ruff to pre-commit
6. Update README.md & Sphinx index with ruff usage & active ruleset

Resources


Installation

1. `poetry add --group -dev ruff`
2. `poetry update`
3. Edit pyproject.toml
  - Add [tool.ruff] section
4. Run initial tests
  - `ruff check .`
  - Assuming that there were issues reported on this first pass, take a look
    at the file names that generated error message. If the errors seem 
    reasonable, have `ruff` attempt to fix the errors by running the command,
    `ruff check --fix .` on them. If you choose to keep the files formatted
    as they currently are, then add them to the `per-file-ignores` section
    of the ruff section, in the `pyproject.toml` file.
  - NOTE: Do not commit any fixed files until AFTER the `nox` sesssion and
    the `pre-commit` changes have been made AND commited. Otherwise, you will
    end up in a sort of "race-condition" with `flake8` wanting to roll back
    any changes that were made by running the `ruff check --fix .` command.
[tool.ruff]
select = [
    "B",    # flake8-bugbear
    "C90",  # mccabe
    "DJ",   # flake8-django
    "E",    # pycodestyle errors
    "F",    # pyflakes
    "I",    # isort
    "S",    # flake8-bandit
    "W",    # pycodestyle warnings
    # "RUF",  # ruff checks
]
ignore = [
    "E501",    # line too long ({width} > {limit} characters)
    # "E203",  # slice notation whitespace (not currently supported)
    "E402",    # module level import not at top of file
    "E722",    # do not use bare except
    # "W503",  # (not currently supported)
    "ERA",     # do not autoremove commented out code
]

# Allow autofix for all enabled rules (when `--fix`) is provided.
fixable = ["A", "B", "C", "D", "E", "F", "G", "I", "N", "Q", "S", "T", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "EM", "ERA", "EXE", "FBT", "ICN", "INP", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PTH", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "TRY", "UP", "YTT"]
unfixable = []

# Exclude a variety of commonly ignored directories.
exclude = [
    ".git",
    ".mypy_cache",
    ".nox",
    ".pytest_cache",
    ".ruff_cache",
    ".venv",
    "__pycache__",
    "__pypackages__",
    "htmlcov",
    "migrations",
    "_build",
    "build",
    "dist",
    "images",
    "media",
    "node_modules",
    "venv",
]

# Same as Black.
line-length = 88

# Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"

# Assume Python 3.11.
target-version = "py311"

[tool.ruff.per-file-ignores]
# "accounts/tests/factories.py" = ["BLK100"] (Not supported)
# "accounts/tests/*" = ["BLK100"] (Not supported)
"accounts/tests/*" = ["S101", "S106"]
"config/test.py" = ["S101", "S106"]
"pages/tests/*" = ["S101", "S106"]

[tool.ruff.mccabe]
# Unlike Flake8, default to a complexity level of 10.
max-complexity = 10

Nox configuration

Edit noxfile.py & remove flake8 references

Configure the lint session as follows:

@nox.session(python=["3.12", "3.11", "3.10", "3.9"])
def lint(session):
    """Lint using ruff."""
    args = session.posargs or locations
    install_with_constraints(
        session,
        "ruff",
    )
    session.run("ruff", "check", *args)

Proceed to run nox tests with the new ruff configuration. Do not run ruff check --fix . until flake8 is replaced in pre-commit config.


Pre-commit configuration

  • Add ruff to the .pre-commit-config.yaml file & remove flake8 NOTE: Ruff's pre-commit hook should be placed after other formatting tools, such as Black and isort, unless you enable autofix, in which case, Ruff's pre-commit hook should run before other formatting tools, as Ruff's autofix behavior can output code changes that require reformatting.
  - repo: https://github.com/charliermarsh/ruff-pre-commit
    rev: 'v0.0.265'
    hooks:
    - id: ruff
      args: [ --fix, --exit-non-zero-on-fix ]

Commit the changes to .pre-commit-config.yaml before running ruff check --fix .

NOTE: Your CI/GitHub Actions may fail here if you have them running lint checks.

Run ruff check --fix . and commit the fixes.

Also note that the URL for pre-commit differs from the main ruff package.


Remove flake8 and related packages

    poetry remove flake8 flake8-bandit flake8-black flake8-bugbear flake8-import-order

Migrate projects identifiers from setup.cfg to pyproject.toml

Add the following to the [tool.poetry] section of the pyproject.toml file:

[tool.poetry]
name = "django-start"
version = "0.2.0"
description = "Basic Django project template"
authors = [
    "Kevin Bowen <kevin.bowen@gmail.com>",
]
maintainers = [
]
license = "MIT"

readme = "README.md"

homepage = ""
repository = "https://github.com/kevinbowen777/repository_name.git"
documentation = ""

keywords = ["django", "web-application", "news"]

classifiers = [
    "Development Status :: 2 - Pre-Alpha",
    "Environment :: Web Environment",
    "Framework :: Django",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
    "Programming Language :: Python",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3 :: Only",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
    "Topic :: Internet :: WWW/HTTP",
]

Delete setup.cfg & .flake8

This assumes that setup.cfg does not contain additional information for other packages(e.g. mypy).

Notes

WHAT IS THE DIFFERENCE BETWEEN django-pytest AND pytest-django?????????

flake8 dependencies

  • flake8 = "^6.0.0"

  • flake8-bandit = "^4.0.0"

  • flake8-black = "^0.3.3"

  • flake8-bugbear = "^23.0.0"

  • flake8-import-order = "^0.18.1"

    poetry remove flake8 flake8-bandit flake8-black flake8-bugbear flake8-import-order

 • Removing attrs (23.1.0)
 • Removing bandit (1.7.5)
 • Removing flake8 (6.0.0)
 • Removing flake8-bandit (4.1.1)
 • Removing flake8-black (0.3.6)
 • Removing flake8-bugbear (23.3.23)
 • Removing flake8-import-order (0.18.2)
 • Removing gitdb (4.0.10)
 • Removing gitpython (3.1.31)
 • Removing pbr (5.11.1)
 • Removing pycodestyle (2.10.0)
 • Removing pyflakes (3.0.1)
 • Removing smmap (5.0.0)
 • Removing stevedore (5.0.0)
 • Updating pyjwt (2.6.0 -> 2.7.0)
 • Updating ruamel-yaml (0.17.24 -> 0.17.26)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment