ruff: Implement flake8-bugbear

This is a big set of rules but flake8-bugbear is extremely popular (~1.5M downloads per month).

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 34 (26 by maintainers)

Commits related to this issue

Most upvoted comments

@charliermarsh Would you be open to implementing B950 ? It’s the only thing missing for me coming from flake8. I could give it a try, but I have no rust experience (yet?).

@harupy is dangerously close to implementing the entire plugin 😉

Nice to see a task list with lots of ✅ 😃

Just updated the list as @harupy is making awesome progress here. We’re now at 50% coverage.

Quick checklist for convenience:

  • B001: bare except
  • B002: ++ -> +=
  • B003: os.environ assigning
  • B004: hasattr(x, ‘__call__’) to test if x is callable
  • B005: .strip() with multi-character strings
  • B006: mutable data structures for argument defaults
  • B007: Loop control variable not used within the loop body
  • B008: function calls in argument defaults
  • B009: getattr(x, ‘attr’) -> x.attr
  • B010: setattr(x, ‘attr’, val) -> x.attr = val
  • B011: assert False calls
  • B012: break, continue or return inside finally blocks
  • B013: length-one tuple literal is redundant
  • B014: Redundant exception types in except (Exception, TypeError)
  • B015: Pointless comparison
  • B016: Cannot raise a literal
  • B017: self.assertRaises(Exception)
  • B018: Found useless expression
  • B019: Use of functools.lru_cache or functools.cache on methods
  • B020: Loop control variable overrides iterable it iterates
  • B021: f-string used as docstring
  • B022: arguments passed to contextlib.suppress
  • B023: functions defined inside a loop using variables redefined in the loop
  • B024: Abstract base class with no abstract method
  • B025: try-except block with duplicate exceptions
  • B026: Star-arg unpacking after a keyword argument is strongly discouraged
  • B027: Empty method in abstract base class

Opinionated:

  • B901: return x in a generator function
  • B902: invalid first argument for method. Use self for instance methods, and cls for class methods
  • B903: Use collections.namedtuple (or typing.NamedTuple) for data classes that only set attributes in an init method
  • B904: Within an except clause, raise exceptions with raise … from err or raise … from None
  • B950: Line too long, generous option

I’m working on B006 implementation.

@SRv6d to make E501 behave like B950 I am just using this:

[tool.ruff]

# Line length to use when enforcing long-lines violations (like `E501`).
line-length = 97  # ceil(1.1 * 88) makes `E501` equivalent to `B950`

B905 was just added:

B905: zip() without an explicit strict= parameter set. strict=True causes the resulting iterator to raise a ValueError if the arguments are exhausted at differing lengths. The strict= argument was added in Python 3.10, so don’t enable this flag for code that should work on ❤️.10. For more information: https://peps.python.org/pep-0618/

I think if we implement B023, we should feel comfortable closing this.

If that is the issue, it’ll be fixed by https://github.com/charliermarsh/ruff/pull/739.

I may have forgotten to include the bugbear settings in the hash key. (I’m on the subway but can fix in a bit, or if someone wants to PR, check out the hash trait implementation on Settings 😃)

@grillazz +1 to the above suggestion. This is the result I get from running on https://github.com/grillazz/fastapi-sqlalchemy-asyncpg’s main branch with the configuration you shared:

$ ruff .
Found 10 error(s).
app/api/nonsense.py:12:79: B008 Do not perform function call `Depends` in argument defaults
app/api/nonsense.py:21:32: B008 Do not perform function call `Depends` in argument defaults
app/api/nonsense.py:27:65: B008 Do not perform function call `Depends` in argument defaults
app/api/nonsense.py:36:32: B008 Do not perform function call `Depends` in argument defaults
app/api/shakespeare.py:15:32: B008 Do not perform function call `Depends` in argument defaults
app/api/stuff.py:16:85: B008 Do not perform function call `Depends` in argument defaults
app/api/stuff.py:30:73: B008 Do not perform function call `Depends` in argument defaults
app/api/stuff.py:39:32: B008 Do not perform function call `Depends` in argument defaults
app/api/stuff.py:45:62: B008 Do not perform function call `Depends` in argument defaults
app/api/stuff.py:54:32: B008 Do not perform function call `Depends` in argument defaults

@grillazz Can you try running ruff --no-cache ...?

@grillazz - This is now supported thanks to @edgarrmondragon. So now you can add this to your pyproject.toml:

[tool.ruff.flake8-bugbear]
extend-immutable-calls = ["fastapi.Depends", "fastapi.Query"]

(Going out in v0.0.115 which is building now.)

@grillazz It’s rather straightforward to add. ~I’m working on it~. PR is https://github.com/charliermarsh/ruff/pull/706 🙂

@charliermarsh for B008 is there any simple way to setup extend-immutable-calls = fastapi.Depends, fastapi.params.Depends ?

That’s awesome, thank you for collating it!

I’m tentatively marking B001 and B950 as complete, since IIUC B001 is the same as E722, and B950 is close enough to E501 that we may not support it independently (I know they’re not exactly the same).