All Articles
Code Quality

Why Tabeer.ai Doesn't Have Black Installed (Even Though Ruff Basically Is Black)

Shahid MalikBy Shahid MalikSeptember 4, 20264 min read

Asked to add Black to a codebase that already had Ruff configured with its own formatter. Here's why that would have meant two tools fighting to do the identical job, and what actually happened instead.

A request to add Black to Tabeer.ai's Django backend came in after Ruff was already installed, configured, and had already reformatted 91 files. Worth being direct about what actually happened: Black wasn't added as a separate dependency. Here's the reasoning, laid out plainly rather than silently skipped.

Ruff's Formatter Is Black, Functionally

ruff format isn't "similar to Black" or "Black-inspired" — it's an explicit, from-scratch reimplementation targeting Black's exact output style, built by the Ruff team specifically so teams already using Black could switch without a diff. The project's own documentation states the intent directly: match Black's formatting decisions, just implemented in Rust instead of Python, for a large speed difference on real codebases.

backend/pyproject.toml already had this configured before Black ever came up:

[tool.ruff.format]
quote-style = "double"
indent-style = "space"

What Installing Black Alongside Ruff Would Actually Mean

Two formatters, configured to produce (as close to) identical output, both running — on every commit if wired into pre-commit, in CI if wired there too. Concretely, that's:

  • Redundant CI time — two passes over the same files for the same result.
  • A second config to keep in sync — Black's own settings would need to mirror Ruff's quote-style and line-length exactly, forever, or the two tools start producing genuinely different output and fighting each other on every file either one touches.
  • Zero net benefit — no code path exists where Ruff's formatter produces different output than Black would, by design. Running both doesn't catch anything the other missed; it just runs the same idea twice.

When Adding Black Separately Would Actually Make Sense

To be fair to the original ask — there are real reasons a team might want Black specifically instead of Ruff's formatter:

  • Already deep in Black-specific tooling (editor integrations, CI badges, docs referencing Black by name) where switching the name of the tool has organizational cost independent of the actual output.
  • Need Black's exact release cadence and stability guarantees for a codebase with a compliance requirement around tool provenance — unusual, but it happens.

Neither applies to this project: Ruff was already the formatter of record, already configured, already run against the whole codebase with the full test suite verified green afterward. There was no existing Black-specific dependency to preserve.

The Actual Decision Rule

When a request asks for a tool that would exactly duplicate a job an already-configured tool is doing, the responsible move isn't silently ignoring the request or installing the redundant tool anyway to check a box — it's surfacing the overlap plainly and explaining the actual tradeoff, the same way the Trivy-vs-Dependabot decision got made on this project: match tooling to what's actually needed, not to a checklist of names.

If you're auditing a Python project's tooling for exactly this kind of redundancy — two linters, two formatters, two of anything doing the same job — get in touch.

Related Articles

Testing

Adding pytest to a Django Project Without Rewriting a Single Test

Tabeer.ai had 659 tests written the standard Django unittest way. Adding pytest didn't mean migrating them — pytest-django runs unittest-style TestCase classes completely unchanged. Here's the actual config and what 'zero-rewrite' really means in practice.

5 min read
Shahid Malik - AI-First Odoo Consultant

Shahid Malik

AI-First Odoo ERP Specialist

Shahid Malik is an AI-first Odoo consultant helping businesses solve complex ERP and business process challenges. His work combines Odoo consulting, process optimization, automation, integrations, migrations, and practical AI solutions to build scalable and reliable business systems.

Book a consultation for your Odoo project
Discuss Your Odoo Project