Skip to content

Implement usethis tool ruff #27

@nathanjmcdougall

Description

@nathanjmcdougall

Motivation
ruff is probably the most popular linter as of late (for good reason) so it's essential we include it in usethis.

Summary of desired feature
Support the addition of ruff to a project using the usethis tool ruff command

Design
Basically, the tool would be handled identically to deptry but there are some additional complications from needing pyproject.toml config. In particular, there needs to be some logic to add the new configuration sections to the pyproject.toml, if they don't already exist. This should be inserted alphabetically within the tool section - in cases where the order is not already alphabetical, place it as low as possible while still retaining order in terms of the subsequent sections.

There will be two hooks corresponding to formatting and checks, which is also different to the deptry case where there is only one hook.

We need to decide which rules to enable. To simplify things, we can just use ruff's defaults, i.e. ["E4", "E7", "E9", "F"], plus a collection of others which are mostly autofixable and relatively uncontroversial:
["I", "UP", "C4", "SIM", "PLE", "PLR", "FURB", "RUF"]

Later, the user could opt-in to a more aggressive approach with a --strict command which tries to enable as many rules as is reasonable (perhaps avoiding the especially controversial ones or ones with too many false positives). For now, we won't implement the --strict flag, so there would be minimal ruff configuration to add in pyproject.toml.

Also, later, for tools managed by usethis, we could ensure particular rules are enabled, e.g. "PT" when the user is using pytest.

When making the strict flag later, here are some thoughts for reference:

  • Some rules are "under-specified" without further configuration, e.g. docstring checking. We should adopt an opinionated default even for controversial points like docstring format. Later, deviations from the defaults could be handled usethis interfaces.
  • We should name each rule family explicitly. We can keep track of new rules added to ruff via the ruff rule --all --output-format json, and have a version test which ensures we haven't missed anything. It is tempting to use "ALL" but this obscures which rules are actually being used. In my view, it is better to name each rule family explicitly, even if this makes the config section longer. This also means we can manually go through each family of rules systematically and not just uncritically adopt new additions.
  • We could include rules conditionally based on whether the framework is being used; for example, NPY rules could be enabled only when numpy is a dependency. The issue with this is that dependencies might change. Even if the framework isn't being used, it doesn't hurt to have the rule enabled. So it's probably not a good idea.

Describe alternatives you've considered
Rather than having a strict flag, we could have the strict behaviour by default. The issue with this is that it is probably too much of a departure from people's expectations and might have too many false positives. Compliance with too many rules is burdensome for users who are not familiar with linters, especially if there is not autofix. It is also potentially very controversial regaring which rules to enable, and a maintenance burden. A strict mode would need a good philosophy on rule inclusion/exclusion so it's not just a fully manual process of constantly reviewing new rules and changes to rules.

I considered the possibility of just using the ruff defaults only without any extra rules, but there are just too many useful linters and it seems a shame not to enable them by default, especially when they are mostly autofix and relatively uncontroversial.

Testing Strategy
Same as for deptry but also include tests relating to the pyproject.toml file contents:

  • checking the contents are correct
  • checking that ruff is able to run in a way that proves it is using the file contents
  • checking the associated messages

Any functions which add/remove contents to/from the pyproject.toml file should be tested too.

Steps

  • Copy deptry's Tool definition, mutatis mutandis.
  • Also copy the deptry CLI function, but add a new call to create pyproject.toml sections, testing along the way.

Acceptance Criteria
New usethis tool ruff CLI interface is available to add ruff including configuration.

Metadata

Metadata

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions