Skip to content

Remove black, use ruff for generated config_models#23588

Open
AAraKKe wants to merge 11 commits intomasterfrom
aarakke/remove-black
Open

Remove black, use ruff for generated config_models#23588
AAraKKe wants to merge 11 commits intomasterfrom
aarakke/remove-black

Conversation

@AAraKKe
Copy link
Copy Markdown
Contributor

@AAraKKe AAraKKe commented May 5, 2026

What does this PR do?

Drops black as a declared dependency of this repo and removes every reference to it (root and ddev pyproject.toml, root and ddev README.md badges, and the update_py_config python-version-bump path). Generated config models are now formatted via ruff format using the repo's centralized [tool.ruff] configuration.

Motivation

ruff format already powers everything else in the toolchain — ddev test -fs, the hatch lint env, and CI's lint step. The only remaining direct uses of black were:

  1. The pinned black==23.12.1 in datadog_checks_dev[cli]
  2. The three apply_black calls inside the model generator
  3. Two [tool.black] config blocks (root + ddev/pyproject.toml) and the python-version-bump logic that touched them
  4. README badges advertising "code style — black"

This PR removes all of that.

Changes

Replace apply_black with a ruff-based helper

  • New datadog_checks_dev/.../configuration/consumers/model/code_formatter.py with format_with_ruff that shells out to python -m ruff format - (uses the active interpreter so the in-venv ruff is always picked up regardless of PATH)
  • Resolves the central [tool.ruff] config via get_root() first, falling back to walking up from the module's own path so unit tests (which never call set_root) still find it
  • Raises loudly on missing ruff / non-zero ruff exit instead of silently degrading
  • The three call sites (model_consumer.py, model_file.py) and the code_formatter parameter plumbing through ModelConsumer.__init__, build_model_file, and validate models are all removed

Make _fix_types whole-document

  • Previously walked line by line. When [tool.black] was removed, datamodel-code-generator's internal black fell back to line-length=88 and started pre-wrapping list[...] across multiple lines, which silently dropped the , ... ellipsis (turning tuple[X, ...] — variable-length tuple — into tuple[X] — single-element tuple). Real type-contract regression.
  • Now joins all model lines, encodes to UTF-8 bytes, and runs the same bracket-tracking pass over the joined buffer (iterating bytes keeps it safe for non-ASCII content in descriptions). The , ... sentinel is inserted after the last non-whitespace byte before ], so it lands on the same line as the inner content.
  • This makes the post-processing independent of how upstream wraps things, which is what unlocked dropping [tool.black] entirely.

Dependency / config / cosmetic cleanup

  • datadog_checks_dev/pyproject.toml: drop black==23.12.1, add ruff==0.11.10 (pinned to match ddev's hatch lint env, with a comment about keeping the pin in sync until commands migrate from datadog_checks_dev into ddev)
  • Root pyproject.toml: drop [tool.black] block and the related comments; remove the stale "formatted with Black" note in the lint-exclusion block
  • ddev/pyproject.toml: drop [tool.black] block
  • ddev/src/ddev/cli/meta/scripts/update_py_config.py: drop the black-handling branch in update_ddev_pyproject_file
  • ddev/tests/cli/meta/scripts/{conftest.py,test_update_py_config.py}: update fixture and assertion (one fewer success in update-python-config → 9 instead of 10)
  • Root README.md and ddev/README.md: replace black badges with ruff

One-time regen of 4 config_models

  • kafka_actions, win32_event_log, and yarn (instance + shared) regenerate with different — but semantically identical — wrapping. They were the only files whose pre-wrapped form was sensitive to the change in upstream line-length default; future regens are stable.
  • Each affected integration has a corresponding <pkg>/changelog.d/23588.fixed entry.

Note on transitive black

  • datamodel-code-generator~=0.25.6 still depends on black and uses it internally during OpenAPIParser.parse(). We can't remove that without bumping the generator (newer 0.26+ supports a formatters choice that includes ruff). With this PR, we no longer declare black, no longer call black, and no longer configure black — but black still rides in via datamodel-code-generator. That's a follow-up change.

Verification

  • All 1098 generated config_model files regenerate cleanly under ddev validate models -s (zero diff against committed state on a fresh run).
  • datadog_checks_dev/tests/tooling/configuration/: 231 passed.
  • ddev/tests/cli/meta/: 36 passed.
  • CI: Run Validations / Validate ✅, Check PR changelog ✅, ddev/datadog_checks_dev test workflows on Linux and Windows ✅, all three affected integration test workflows ✅.

Review checklist (to be filled by reviewers)

  • Feature or bugfix MUST have appropriate tests (unit, integration, e2e)
  • Add the `qa/skip-qa` label if the PR doesn't need to be tested during QA.
  • If you need to backport this PR to another branch, you can add the `backport/` label to the PR and it will automatically open a backport PR once this one is merged

…ig models

- Remove explicit `black==23.12.1` from `datadog_checks_dev`
- Replace `apply_black` calls in the model consumer with `ruff format -`,
  using the repo's centralized `[tool.ruff]` configuration
- Drop the now-unused `code_formatter` plumbing through `ModelConsumer` /
  `build_model_file` / `validate models`
- Drop the [tool.black] block from `ddev/pyproject.toml` and the matching
  python-version-bump logic in `update_py_config.py` (with test fixture)
- Update README badge from black to ruff

The root `[tool.black]` section is kept (with an explanatory comment)
because `datamodel-code-generator` reads it transitively through its own
internal formatter, and removing it changes line-length to 88 which
breaks our list[...] -> tuple[..., ...] line-by-line transform.
@AAraKKe AAraKKe added the qa/skip-qa Automatically skip this PR for the next QA label May 5, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

⚠️ Major version bump
The changelog type changed or removed was used in this Pull Request, so the next release will bump major version. Please make sure this is a breaking change, or use the fixed or added type instead.

@datadog-datadog-prod-us1-2
Copy link
Copy Markdown

datadog-datadog-prod-us1-2 Bot commented May 5, 2026

Tests

Fix all issues with BitsAI or with Cursor

⚠️ Warnings

🧪 1 Test failed

test_e2e_profile_cisco_asr_1001x from test_e2e_core_vs_python.py   View in Datadog   (Fix with Cursor)
[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] 01-check-apikey.sh: executing... 
[cont-init.d] 01-check-apikey.sh: exited 0.
[cont-init.d] 50-ci.sh: executing... 
[cont-init.d] 50-ci.sh: exited 0.
[cont-init.d] 50-ecs-managed.sh: executing... 
...

ℹ️ Info

No other issues found (see more)

❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 95.63%
Overall Coverage: 87.33% (+0.13%)

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: e6530d0 | Docs | Datadog PR Page | Give us feedback!

@codecov
Copy link
Copy Markdown

codecov Bot commented May 5, 2026

Codecov Report

❌ Patch coverage is 95.62842% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.82%. Comparing base (2559b27) to head (e6530d0).

Additional details and impacted files
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

AAraKKe added 3 commits May 5, 2026 12:52
… ruff

CI installs ddev with `pip install -e ./datadog_checks_dev[cli]` and never
adds ruff to PATH. The previous helper called `shutil.which('ruff')` and
silently returned the input unchanged when ruff was missing — leaving long
lines and missing wraps in 401 generated config-model files, surfacing as
"not in sync" in the validate workflow.

- Declare `ruff>=0.11` in `datadog_checks_dev[cli]` so the package is
  always installed alongside the model generator.
- Switch the helper to `sys.executable -m ruff` so the in-venv package is
  used regardless of PATH.
- Raise loudly on missing ruff or non-zero ruff exit instead of silently
  degrading, so any future regression fails the workflow with a clear error.
Make `_fix_types` operate on the joined document (as UTF-8 bytes) instead
of line by line, so the bracket-tracking pass works regardless of how
datamodel-code-generator's internal formatter wrapped `list[...]`. Place
the `, ...` sentinel right after the last non-whitespace byte before the
closing `]`, so output stays on the previous content line even when the
parser pre-wrapped the closing bracket onto its own line.

With those changes the generator no longer relies on `[tool.black]`
existing in the repo, so the section and its accompanying comment are
removed from `pyproject.toml`. The black-related comment near the
config_models lint exclusion and the black badge in `README.md` go too.

Four config_models files (kafka_actions, win32_event_log, yarn x2)
regenerate with different — but semantically identical — wrapping. They
were the only ones whose pre-wrapped form was sensitive to the change in
upstream line-length default; future regens are stable.
@AAraKKe AAraKKe changed the title Drop black as a direct dependency, use ruff format for generated config models Remove black, use ruff for generated config_models May 5, 2026
AAraKKe added 5 commits May 5, 2026 14:59
- Replace remaining "code style - black" references in developer docs
  (`docs/developer/index.md` badge, `docs/developer/guidelines/style.md`
  style section, link reference) with ruff equivalents.
- Update the stale `ddev test postgres -l` example output in
  `docs/developer/testing.md` to drop `black==22.12.0` and reflect the
  current lint env contents (`ruff==0.11.10`, `pydantic==2.11.5`).
- Move the "ruff is not installed" install hint in `format_with_ruff`
  from the `FileNotFoundError` branch to the `CalledProcessError` branch
  and gate it on `"No module named 'ruff'"` in stderr — the previous
  layout was effectively dead code because `sys.executable` always
  resolves, so missing-ruff surfaces as a non-zero exit, not a missing
  binary.
- Add `tests/tooling/configuration/consumers/model/test_fix_types.py`
  with focused coverage for the `_fix_types` post-processing pass: the
  multiline-wrapped `list[Literal[...]]` regression case the PR was
  written to fix, dict and nested-list translations, unicode in
  descriptions, and verbatim pass-through when no `list[`/`dict[`
  is present.
code_formatter.py:
- Guard `_resolve_ruff_config` with `if root_str:` so an unset
  `get_root()` (returns '') doesn't fall into the `Path('').is_dir()`
  branch (which is True — it resolves to CWD), and unit tests actually
  walk back to the repo pyproject.toml as the docstring claims.
- Replace the loose `'[tool.ruff' in text` substring with a line-anchored
  scan that only matches actual TOML table headers (`[tool.ruff]` or
  `[tool.ruff.…]`), so a comment or string value can't false-positive.
- Surface argv (via `shlex.join`), stderr, and stdout in the error
  message for non-missing-package failures, so a future ruff config
  change emitting actionable output is debuggable from the message alone.

Tests:
- New `test_code_formatter.py` (17 tests): direct coverage for
  `format_with_ruff` (line wrapping, quote-style preservation, short
  passthrough, missing-ruff hint, full-context error on other failures)
  and `_resolve_ruff_config` (root path success, fallback walk on empty
  root, fallback walk when root has no `[tool.ruff]`, returns None when
  nothing is found, parametrized header recognition for `_has_ruff_section`).
- `test_update_py_config.py`: add explicit content assertions on the
  rewritten `ddev/pyproject.toml` — no `[tool.black]` block survives,
  `[tool.ruff].target-version` is updated to the new pinned version, the
  old token is gone. Captures the actual contract instead of relying on
  the success-counter being 9.
This PR bumps `datadog-checks-dev` to 39 (`black` is dropped from `[cli]`
extras, so per semver it's a major). The current `~=38.0` constraint in
ddev's `pyproject.toml` would block any GitHub Action that installs both
packages from the local repo — `pip install -e ./ddev` would fail to
resolve the local dcd 39 against ddev's pin.

Relax the pin to `>=38.0,<40` for the duration of the gap between this
PR landing and the next ddev release. The release PR for ddev MUST
tighten this back to `~=39.0`.
@dd-octo-sts
Copy link
Copy Markdown
Contributor

dd-octo-sts Bot commented May 5, 2026

Validation Report

All 20 validations passed.

Show details
Validation Description Status
agent-reqs Verify check versions match the Agent requirements file
ci Validate CI configuration and Codecov settings
codeowners Validate every integration has a CODEOWNERS entry
config Validate default configuration files against spec.yaml
dep Verify dependency pins are consistent and Agent-compatible
http Validate integrations use the HTTP wrapper correctly
imports Validate check imports do not use deprecated modules
integration-style Validate check code style conventions
jmx-metrics Validate JMX metrics definition files and config
labeler Validate PR labeler config matches integration directories
legacy-signature Validate no integration uses the legacy Agent check signature
license-headers Validate Python files have proper license headers
licenses Validate third-party license attribution list
metadata Validate metadata.csv metric definitions
models Validate configuration data models match spec.yaml
openmetrics Validate OpenMetrics integrations disable the metric limit
package Validate Python package metadata and naming
readmes Validate README files have required sections
saved-views Validate saved view JSON file structure and fields
version Validate version consistency between package and changelog

View full run

@AAraKKe AAraKKe marked this pull request as ready for review May 5, 2026 13:20
@AAraKKe AAraKKe requested review from a team as code owners May 5, 2026 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants