Skip to content

Commit

Permalink
Use Ruff for linting and formatting (#99)
Browse files Browse the repository at this point in the history
Ruff is a Python linter and formatter that has gained popularity due to
its high performance and numerous capabilities.
https://docs.astral.sh/ruff/

Now that Ruff has released its first minor version series and has a
versioning policy, it's a good time to consider adopting it.
https://docs.astral.sh/ruff/versioning/
https://astral.sh/blog/ruff-v0.1.0

This commit will replace Black, Flake8, and isort with Ruff.

Black

Ruff is a drop-in replacement for Black. No additional configuration is
necessary.

Ruff supports opt-in docstring formatting with `docstring-code-format`.
The format is compatible with Black string formatting.

```toml
[tool.ruff.format]
docstring-code-format = true
```

https://docs.astral.sh/ruff/faq/
https://docs.astral.sh/ruff/formatter/#docstring-formatting
https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#strings

Flake8

Ruff is a drop-in replacement for Flake8. No additional configuration is
necessary. In addition to replacing Flake8 itself, Ruff can also replace
many Flake8 plugins and related projects.

isort

Ruff is not a drop-in replacement for isort at this time. Additional
configuration is needed.

1. Import sorting is opt-in. Ruff will not automatically sort imports.
   The `extend-select` setting is needed with the `I` ruleset.
2. There is no `src_paths` setting. The `src` and `known-first-party`
   settings are used instead. The Ruff FAQ currently says, "Ruff accepts
   a `src` option that in your `pyproject.toml`, `ruff.toml`, or
   `.ruff.toml` file, which specifies the directories that Ruff should
   consider when determining whether an import is first-party," making
   it sound like only `src` would be needed. However, to match isort
   behavior, both `src` and `known-first-party` may need to be set to
   the same list of directories.
3. Although isort is a formatter, Ruff does not run import sorting with
   the Ruff formatter. The Ruff linter is used instead
   (`ruff check --fix`).

Taken together, Ruff configuration settings in `pyproject.toml` related
to import sorting look like this:

```toml
[tool.ruff]
extend-select = ["I"]
src = ["package_name", "tests"]

[tool.ruff.lint.isort]
known-first-party = ["package_name", "tests"]
```

https://docs.astral.sh/ruff/faq/
https://docs.astral.sh/ruff/settings/
https://docs.astral.sh/ruff/rules/#isort-i
https://pycqa.github.io/isort/docs/configuration/options.html#src-paths

Notes on additional tools

Hatch

Hatch 1.8.0 introduced static analysis with Ruff. Although this is a
promising feature of Hatch, it will not be used at this time because of
differences between Hatch default settings and Ruff default settings,
and because it is not yet possible to fully override the Hatch default
settings (though this will likely be improved in the next release).
https://hatch.pypa.io/1.9/config/static-analysis/#default-settings
https://docs.astral.sh/ruff/configuration/
https://hatch.pypa.io/latest/blog/2023/12/11/hatch-v180/#static-analysis

VSCode

To use Ruff in VSCode, install `charliermarsh.ruff` from the VSCode
extension marketplace or Open VSX marketplace (for VSCodium), then
update `settings.json` like this:

```json
{
  "[python]": {
    "editor.codeActionsOnSave": {
      "source.fixAll": "always",
      "source.organizeImports": "always"
    },
    "editor.defaultFormatter": "charliermarsh.ruff",
    "editor.formatOnSave": true
  },
  "ruff.lint.args": ["--extend-select=I"]
}
```

https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff
https://open-vsx.org/extension/charliermarsh/ruff
https://vscodium.com/
  • Loading branch information
br3ndonland committed Jan 14, 2024
1 parent 696c43d commit 35e37a7
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 32 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ _Docker images and utilities to power your Python APIs and help you ship faster.

[![PyPI](https://img.shields.io/pypi/v/inboard?color=success)](https://pypi.org/project/inboard/)
[![GitHub Container Registry](https://img.shields.io/badge/github%20container%20registry-inboard-success)](https://github.com/br3ndonland/inboard/pkgs/container/inboard)
[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://black.readthedocs.io/en/stable/)
[![coverage](https://img.shields.io/badge/coverage-100%25-brightgreen?logo=pytest&logoColor=white)](https://coverage.readthedocs.io/en/latest/)
[![builds](https://github.com/br3ndonland/inboard/workflows/builds/badge.svg)](https://github.com/br3ndonland/inboard/actions)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/ef2798f758e03fa659d1ba2973ddd59515400978/assets/badge/v2.json)](https://github.com/astral-sh/ruff)

[![Mentioned in Awesome FastAPI](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/mjhea0/awesome-fastapi)

Expand Down
10 changes: 1 addition & 9 deletions docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,15 +204,7 @@ Code quality checks can be run using the Hatch scripts in _pyproject.toml_.

### Code style

- **Python code is formatted with [Black](https://black.readthedocs.io/en/stable/)**. Configuration for Black is stored in _[pyproject.toml](https://github.com/br3ndonland/inboard/blob/HEAD/pyproject.toml)_.
- **Python imports are organized automatically with [isort](https://pycqa.github.io/isort/)**.
- The isort package organizes imports in three sections:
1. Standard library
2. Dependencies
3. Project
- Within each of those groups, `import` statements occur first, then `from` statements, in alphabetical order.
- You can run isort from the command line with `hatch run isort .`.
- Configuration for isort is stored in _[pyproject.toml](https://github.com/br3ndonland/inboard/blob/HEAD/pyproject.toml)_.
- Python code is formatted with [Ruff](https://docs.astral.sh/ruff/). Ruff configuration is stored in _pyproject.toml_.
- Other web code (JSON, Markdown, YAML) is formatted with [Prettier](https://prettier.io/).

### Static type checking
Expand Down
18 changes: 11 additions & 7 deletions docs/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,8 @@ The _pyproject.toml_ could look like this:

[project.optional-dependencies]
checks = [
"black",
"flake8",
"isort",
"mypy",
"ruff",
]
docs = [
"mkdocs-material",
Expand Down Expand Up @@ -133,10 +131,6 @@ The _pyproject.toml_ could look like this:
[tool.hatch.version]
path = "package_name/__init__.py"

[tool.isort]
profile = "black"
src_paths = ["package_name", "tests"]

[tool.mypy]
files = ["**/*.py"]
plugins = "pydantic.mypy"
Expand All @@ -148,6 +142,16 @@ The _pyproject.toml_ could look like this:
minversion = "6.0"
testpaths = ["tests"]

[tool.ruff]
extend-select = ["I"]
src = ["package_name", "tests"]

[tool.ruff.format]
docstring-code-format = true

[tool.ruff.lint.isort]
known-first-party = ["package_name", "tests"]

```

The _Dockerfile_ could look like this:
Expand Down
3 changes: 1 addition & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ _Docker images and utilities to power your Python APIs and help you ship faster.

[![PyPI](https://img.shields.io/pypi/v/inboard?color=success)](https://pypi.org/project/inboard/)
[![GitHub Container Registry](https://img.shields.io/badge/github%20container%20registry-inboard-success)](https://github.com/br3ndonland/inboard/pkgs/container/inboard)
[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://black.readthedocs.io/en/stable/)
[![coverage](https://img.shields.io/badge/coverage-100%25-brightgreen?logo=pytest&logoColor=white)](https://coverage.readthedocs.io/en/latest/)
[![builds](https://github.com/br3ndonland/inboard/workflows/builds/badge.svg)](https://github.com/br3ndonland/inboard/actions)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/ef2798f758e03fa659d1ba2973ddd59515400978/assets/badge/v2.json)](https://github.com/astral-sh/ruff)

[![Mentioned in Awesome FastAPI](https://awesome.re/mentioned-badge-flat.svg)](https://github.com/mjhea0/awesome-fastapi)

Expand Down
27 changes: 15 additions & 12 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,8 @@ requires-python = ">=3.8.1,<4"

[project.optional-dependencies]
checks = [
"black>=23,<24",
"flake8>=6,<7",
"isort>=5,<6",
"mypy==1.8.0",
"ruff>=0.1,<0.2",
]
docs = [
"mkdocs-material>=9,<10",
Expand Down Expand Up @@ -113,16 +111,15 @@ path = ".venv"

[tool.hatch.envs.default.scripts]
check = [
"black --check --diff .",
"isort --check --diff .",
"flake8 --extend-exclude=.venv,bin,build,cache,dist,lib --max-line-length=88",
"ruff check",
"ruff format --check",
"mypy",
"npx -s -y prettier@'^2' . --check",
"npx -s -y cspell --dot --gitignore *.md **/*.md",
]
format = [
"black .",
"isort .",
"ruff check --fix",
"ruff format",
"npx -s -y prettier@'^2' . --write",
]

Expand All @@ -149,10 +146,6 @@ path = ".venv"
[tool.hatch.version]
path = "inboard/__init__.py"

[tool.isort]
profile = "black"
src_paths = ["inboard", "tests"]

[tool.mypy]
files = ["**/*.py"]
plugins = "pydantic.mypy"
Expand All @@ -163,3 +156,13 @@ strict = true
addopts = "-q"
minversion = "6.0"
testpaths = ["tests"]

[tool.ruff]
extend-select = ["I"]
src = ["inboard", "tests"]

[tool.ruff.format]
docstring-code-format = true

[tool.ruff.lint.isort]
known-first-party = ["inboard", "tests"]

0 comments on commit 35e37a7

Please sign in to comment.