Skip to content

[ruff] Detect PLC0207 on chained str.split() calls#23275

Merged
ntBre merged 1 commit intoastral-sh:mainfrom
harupy:fix/plc0207-chained-splits
Feb 18, 2026
Merged

[ruff] Detect PLC0207 on chained str.split() calls#23275
ntBre merged 1 commit intoastral-sh:mainfrom
harupy:fix/plc0207-chained-splits

Conversation

@harupy
Copy link
Contributor

@harupy harupy commented Feb 14, 2026

Summary

Fixes #23105

Extend the target-instance unwrapping loop to also recurse through split/rsplit Call expressions so that chained splits like s.split('(')[0].split('[')[0] are detected.

Test plan

Added test cases for chained splits.

🤖 Generated with Claude Code

Fixes astral-sh#23105

The `is_string` check in PLC0207 failed to recognize that `str.split()`
returns `list[str]`, so subscripting it yields a `str`. This caused the
rule to miss chained splits like `s.split('(')[0].split('[')[0]`.

Extend the target-instance unwrapping loop to also recurse through
`split`/`rsplit` Call expressions, reaching the original string value.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@harupy harupy changed the title Detect PLC0207 on chained str.split() calls Detect PLC0207 on chained str.split() calls Feb 14, 2026
@harupy harupy changed the title Detect PLC0207 on chained str.split() calls [ruff] Detect PLC0207 on chained str.split() calls Feb 14, 2026
@astral-sh-bot
Copy link

astral-sh-bot bot commented Feb 14, 2026

ruff-ecosystem results

Linter (stable)

ℹ️ ecosystem check detected linter changes. (+7 -0 violations, +0 -0 fixes in 4 projects; 52 projects unchanged)

apache/airflow (+1 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --no-fix --output-format concise --no-preview --select ALL

+ providers/google/src/airflow/providers/google/cloud/utils/credentials_provider.py:484:16: PLC0207 [*] String is split more times than necessary

apache/superset (+3 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --no-fix --output-format concise --no-preview --select ALL

+ superset/db_engine_specs/lint_metadata.py:100:17: PLC0207 [*] String is split more times than necessary
+ superset/db_engine_specs/lint_metadata.py:100:17: PLC0207 [*] String is split more times than necessary
+ superset/db_engine_specs/lint_metadata.py:100:17: PLC0207 [*] String is split more times than necessary

pypa/cibuildwheel (+1 -0 violations, +0 -0 fixes)

+ cibuildwheel/selector.py:78:26: PLC0207 [*] String is split more times than necessary

home-assistant/core (+2 -0 violations, +0 -0 fixes)

+ homeassistant/components/bang_olufsen/util.py:37:12: PLC0207 [*] String is split more times than necessary
+ homeassistant/components/roomba/config_flow.py:343:12: PLC0207 [*] String is split more times than necessary

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
PLC0207 7 7 0 0 0

Linter (preview)

ℹ️ ecosystem check detected linter changes. (+7 -0 violations, +0 -0 fixes in 4 projects; 52 projects unchanged)

apache/airflow (+1 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --no-fix --output-format concise --preview --select ALL

+ providers/google/src/airflow/providers/google/cloud/utils/credentials_provider.py:484:16: PLC0207 [*] String is split more times than necessary

apache/superset (+3 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --no-fix --output-format concise --preview --select ALL

+ superset/db_engine_specs/lint_metadata.py:100:17: PLC0207 [*] String is split more times than necessary
+ superset/db_engine_specs/lint_metadata.py:100:17: PLC0207 [*] String is split more times than necessary
+ superset/db_engine_specs/lint_metadata.py:100:17: PLC0207 [*] String is split more times than necessary

pypa/cibuildwheel (+1 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --no-fix --output-format concise --preview

+ cibuildwheel/selector.py:78:26: PLC0207 [*] String is split more times than necessary

home-assistant/core (+2 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --no-fix --output-format concise --preview

+ homeassistant/components/bang_olufsen/util.py:37:12: PLC0207 [*] String is split more times than necessary
+ homeassistant/components/roomba/config_flow.py:343:12: PLC0207 [*] String is split more times than necessary

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
PLC0207 7 7 0 0 0

Copy link
Contributor

@ntBre ntBre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

It feels slightly silly to do this since it's just a special case of inferring that the target of the split call is a string, but I'm okay with special casing it since it comes up several times in the ecosystem, and it's also a very obvious false negative since the first part of the same expression gets a diagnostic.

I also double-checked that the fixes apply cleanly in one pass:

just run check --select PLC0207 --fix - <<'EOF'
SEQ = ""
SEQ.split("(")[0].split("[")[0].split(".")[-1]
EOF
cargo run -p ruff -- check --select PLC0207 --fix -
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.16s
     Running `target/debug/ruff check --select PLC0207 --fix -`
warning: Detected debug build without --no-cache.
SEQ = ""
SEQ.split("(", maxsplit=1)[0].split("[", maxsplit=1)[0].rsplit(".", maxsplit=1)[-1]
Found 3 errors (3 fixed, 0 remaining).

I'm always slightly wary about overlapping fixes since I don't think our fixtures exercise that, but this works well!

@ntBre ntBre added the rule Implementing or modifying a lint rule label Feb 18, 2026
@ntBre ntBre merged commit b996bdd into astral-sh:main Feb 18, 2026
43 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rule Implementing or modifying a lint rule

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ruff rule PLC0207 (and autofix) misses obvious rule propogation on chained splits

2 participants