Skip to content

B018: report map(), filter() and other lazy builtins used as statements - #605

Merged
cooperlees merged 1 commit into
PyCQA:mainfrom
LuisFigueroaG:fix/b018-lazy-builtin-calls
Oct 24, 2026
Merged

cooperlees merged 1 commit into
PyCQA:mainfrom
LuisFigueroaG:fix/b018-lazy-builtin-calls

Conversation

@LuisFigueroaG

Copy link
Copy Markdown
Contributor

Refs #452.

B018 already reports a bare call to a builtin without side effects, like sorted(x) or isinstance(x, int), but not the ones that return a lazy iterator, where the statement looks like it does something and doesn't:

map(print, items)  # nothing iterates over the map, so print never runs
reversed(items)  # meant items.reverse()

This adds map, filter, reversed, zip and enumerate. The first three are the calls @JelleZijlstra listed in #452 next to sorted, which is already covered; zip and enumerate are lazy in the same way. It's also an easy leftover from Python 2, where map() and filter() returned lists. iter stays out, since a bare iter(x) is there to call x.__iter__().

Like the operations from #579, a call directly in a try/with block is left alone. These check their arguments right away, and tests call them only to see that raise, as CPython does with with self.assertRaises(TypeError): zip(BadIterable()) and try: reversed(f) except TypeError:. As with the other builtins, the arguments aren't looked at: in map(handle, fetch()), fetch runs but handle never does, so that's still reported.

On CPython's Lib from main (2,071 files, tests included), Ubuntu's dist-packages (2,145) and about 14,000 files from other projects, this adds 3 reports: filter(identity, Squares(5)) in test_builtin.py, which tests filter itself, and two enumerate(...) lines in a black formatter fixture. Both files already get B018.

Tests are in tests/eval_files/b018_lazy_calls.py. b905_py310.py and b912_py314.py call zip() and map() as statements, so I assigned their results, like #547 did in b023.py. tox py310–py315 and pre-commit pass.

map(), filter(), reversed(), zip() and enumerate() return lazy iterators,
so `map(print, items)` on its own line never calls `print`. They are now
reported like the side-effect-free builtins B018 already covers.

Like operations, a call directly in a `try` or `with` block is left
alone, since these check their arguments right away and a test may call
one only to see that raise. iter() is left out: it calls `__iter__`
right away, which is what a bare `iter(x)` is for.

The B905 and B912 tests call zip() and map() as statements, so their
results are now assigned.

Refs PyCQA#452

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The scoped detection change, exemptions, documentation, and fixture updates are consistent, with no unresolved findings.

No open issues 🎉

What changed in this PR

Extends B018’s useless-expression detection to report discarded calls to lazy builtins, addressing another case discussed in #452.

Changes:

  • Detects standalone map, filter, reversed, zip, and enumerate calls while preserving direct try/with exemptions.
  • Adds coverage for reported calls and intentional exclusions, and adjusts existing fixtures to avoid unrelated B018 diagnostics.
  • Documents the expanded behavior and adds a changelog entry.
File Description
tests/​eval_files/​b912_py314.py Assigns map results and adjusts expected B912 columns.
tests/​eval_files/​b905_py310.py Assigns zip results and adjusts expected B905 columns.
tests/​eval_files/​b018_lazy_calls.py Covers discarded lazy calls, consumed results, and raising-block exemptions.
README.rst Documents lazy-call detection and records the change.
bugbear.py Adds lazy builtin names and integrates them into B018 detection.

Review effort: Balanced

@cooperlees cooperlees left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM - Thanks for more work on reported issues!

@cooperlees
cooperlees merged commit 7a66efc into PyCQA:main Oct 24, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants