ruff icon indicating copy to clipboard operation
ruff copied to clipboard

feat(rules): Implement flake8-bugbear B038 rule

Open mimre25 opened this issue 1 year ago • 9 comments

Summary

This PR adds the implementation for the current flake8-bugbear's B038 rule. The B038 rule checks for mutation of loop iterators in the body of a for loop and alerts when found.

Rational: Editing the loop iterator can lead to undesired behavior and is probably a bug in most cases.

Closes #9511.

Note there will be a second iteration of B038 implemented in flake8-bugbear soon, and this PR currently only implements the weakest form of the rule. I'd be happy to also implement the further improvements to B038 here in ruff :slightly_smiling_face: See https://github.com/PyCQA/flake8-bugbear/issues/454 for more information on the planned improvements.

Test Plan

Re-using the same test file that I've used for flake8-bugbear, which is included in this PR (look for the B038.py file).

Note: this is my first time using rust (beside rustlings) - I'd be very happy about thorough feedback on what I could've done better :slightly_smiling_face: - Bring it on :grinning:

mimre25 avatar Jan 19 '24 15:01 mimre25

Awesome, thank you! Excited to review, I'll give it a close read per request :)

charliermarsh avatar Jan 19 '24 16:01 charliermarsh

Thank you! Left some comments -- feel free to ask questions.

charliermarsh avatar Jan 21 '24 15:01 charliermarsh

Do you have any suggestion on how to set up the work environment?

In general I think rust's incremental builds are a good idea, but damn they eat up like 10+gb for this project :grimacing:

mimre25 avatar Jan 25 '24 13:01 mimre25

Awesome, I should be able to review and merge this today!

charliermarsh avatar Jan 25 '24 15:01 charliermarsh

@charliermarsh please hold off from merging, I still want to remote the to_name_str function and use collect_call_path instead.

Also, in flake8-bugbear there is currently the motion going on to make this an optional rule (disabled per default) as there are some false positives stemming from the python standard library - See the discussion in https://github.com/PyCQA/flake8-bugbear/issues/455

mimre25 avatar Jan 25 '24 17:01 mimre25

@mimre25 - Roger that!

charliermarsh avatar Jan 25 '24 17:01 charliermarsh

@mimre25 - I'm going to convert to draft for now just to help manage our review workflow.

charliermarsh avatar Jan 25 '24 17:01 charliermarsh

I close because it is stale. Please re-open if you plan to follow up on the remaining work.

MichaReiser avatar Apr 08 '24 07:04 MichaReiser

Sorry for leaving this stale for so long.

I was quite busy and had planned to finish this up in the next couple of weeks.

mimre25 avatar Apr 08 '24 14:04 mimre25

Alright, I finally got around to finish this.

This is now on parity with flake8-bugbear's B909 (it was renamed).

Main new features in the new commits are described in https://github.com/PyCQA/flake8-bugbear/issues/454. Further, the rule now allows mutations before an unconditional break.

mimre25 avatar Apr 11 '24 15:04 mimre25

Thanks! I'll take a look.

charliermarsh avatar Apr 11 '24 15:04 charliermarsh

ruff-ecosystem results

Linter (stable)

ℹ️ ecosystem check encountered linter errors. (no lint changes; 1 project error)

pypa/setuptools (error)

Cannot overwrite a value (at line 26, column 2)

Linter (preview)

ℹ️ ecosystem check detected linter changes. (+5 -0 violations, +0 -0 fixes in 3 projects; 1 project error; 40 projects unchanged)

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

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

+ airflow/models/taskinstance.py:3758:17: B909 Mutation to loop iterable `new_dict` during iteration
+ airflow/providers/openlineage/sqlparser.py:353:13: B909 Mutation to loop iterable `tables` during iteration
python/mypy (+1 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --output-format concise --preview

+ mypy/build.py:3200:21: B909 Mutation to loop iterable `new` during iteration
scikit-build/scikit-build (+2 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --output-format concise --preview

+ tests/pytest_helpers.py:49:13: B909 Mutation to loop iterable `expected_content` during iteration
+ tests/pytest_helpers.py:92:13: B909 Mutation to loop iterable `expected_content` during iteration
pypa/setuptools (error)

ruff check --no-cache --exit-zero --ignore RUF9 --output-format concise --preview

Cannot overwrite a value (at line 26, column 2)
Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
B909 5 5 0 0 0

github-actions[bot] avatar Apr 11 '24 19:04 github-actions[bot]

There are some false positives in here. For example:

for auth_method in authentication_methods_dict:
    authentication_methods_dict[auth_method] = True

That's probably the most common?

charliermarsh avatar Apr 11 '24 19:04 charliermarsh