Commit Graph

6603 Commits

Author SHA1 Message Date
Wei Lee 6e9fb9af38
[`airflow`] Skip attribute check in try catch block (`AIR301`) (#17790)
<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

Skip attribute check in try catch block (`AIR301`)

## Test Plan

<!-- How was it tested? -->
update
`crates/ruff_linter/resources/test/fixtures/airflow/AIR301_names_try.py`
2025-05-05 10:01:05 -04:00
Wei Lee a507c1b8b3
[`airflow`] Remove `airflow.utils.dag_parsing_context.get_parsing_context` (`AIR301`) (#17852)
<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->
Remove `airflow.utils.dag_parsing_context.get_parsing_context` from
AIR301 as it has been moved to AIR311

## Test Plan

<!-- How was it tested? -->

the test fixture was updated in the previous PR
2025-05-05 09:31:57 -04:00
David Peter 5a91badb8b
[ty] Move 'scipy' to list of 'good' projects (#17850)
## Summary

Adds `scipy` as a new project to `good.txt` as a follow-up to #17849.
2025-05-05 13:52:57 +02:00
David Peter 1945bfdb84
[ty] Fix standalone expression type retrieval in presence of cycles (#17849)
## Summary

When entering an `infer_expression_types` cycle from
`TypeInferenceBuilder::infer_standalone_expression`, we might get back a
`TypeInference::cycle_fallback(…)` that doesn't actually contain any new
types, but instead it contains a `cycle_fallback_type` which is set to
`Some(Type::Never)`. When calling `self.extend(…)`, we therefore don't
really pull in a type for the expression we're interested in. This
caused us to panic if we tried to call `self.expression_type(…)` after
`self.extend(…)`.

The proposed fix here is to retrieve that type from the nested
`TypeInferenceBuilder` directly, which will correctly fall back to
`cycle_fallback_type`.

## Details

I minimized the second example from #17792 a bit further and used this
example for debugging:

```py
from __future__ import annotations

class C: ...

def f(arg: C):
    pass

x, _ = f(1)

assert x
```

This is self-referential because when we check the assignment statement
`x, _ = f(1)`, we need to look up the signature of `f`. Since evaluation
of annotations is deferred, we look up the public type of `C` for the
`arg` parameter. The public use of `C` is visibility-constraint by "`x`"
via the `assert` statement. While evaluating this constraint, we need to
look up the type of `x`, which in turn leads us back to the `x, _ =
f(1)` definition.

The reason why this only showed up in the relatively peculiar case with
unpack assignments is the code here:


78b4c3ccf1/crates/ty_python_semantic/src/types/infer.rs (L2709-L2718)

For a non-unpack assignment like `x = f(1)`, we would not try to infer
the right-hand side eagerly. Instead, we would enter a
`infer_definition_types` cycle that handles the situation correctly. For
unpack assignments, however, we try to infer the type of `value`
(`f(1)`) and therefore enter the cycle via `standalone_expression_type
=> infer_expression_type`.

closes #17792 

## Test Plan

* New regression test
* Made sure that we can now run successfully on scipy => see #17850
2025-05-05 13:52:08 +02:00
Dylan a95c73d5d0
Implement deferred annotations for Python 3.14 (#17658)
This PR updates the semantic model for Python 3.14 by essentially
equating "run using Python 3.14" with "uses `from __future__ import
annotations`".

While this is not technically correct under the hood, it appears to be
correct for the purposes of our semantic model. That is: from the point
of view of deciding when to parse, bind, etc. annotations, these two
contexts behave the same. More generally these contexts behave the same
unless you are performing some kind of introspection like the following:


Without future import:
```pycon
>>> from annotationlib import get_annotations,Format
>>> def foo()->Bar:...
...
>>> get_annotations(foo,format=Format.FORWARDREF)
{'return': ForwardRef('Bar')}
>>> get_annotations(foo,format=Format.STRING)
{'return': 'Bar'}
>>> get_annotations(foo,format=Format.VALUE)
Traceback (most recent call last):
[...]
NameError: name 'Bar' is not defined
>>> get_annotations(foo)
Traceback (most recent call last):
[...]
NameError: name 'Bar' is not defined
```

With future import:
```
>>> from __future__ import annotations
>>> from annotationlib import get_annotations,Format
>>> def foo()->Bar:...
...
>>> get_annotations(foo,format=Format.FORWARDREF)
{'return': 'Bar'}
>>> get_annotations(foo,format=Format.STRING)
{'return': 'Bar'}
>>> get_annotations(foo,format=Format.VALUE)
{'return': 'Bar'}
>>> get_annotations(foo)
{'return': 'Bar'}
```

(Note: the result of the last call to `get_annotations` in these
examples relies on the fact that, as of this writing, the default value
for `format` is `Format.VALUE`).

If one day we support lint rules targeting code that introspects using
the new `annotationlib`, then it is possible we will need to revisit our
approximation.

Closes #15100
2025-05-05 06:40:36 -05:00
David Peter 78b4c3ccf1
[ty] Minor typo in environment variable name (#17848) 2025-05-05 10:25:48 +00:00
renovate[bot] 2485afe640
Update pre-commit dependencies (#17840)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-05 07:36:09 +00:00
Micha Reiser e95130ad80
Introduce `TY_MAX_PARALLELISM` environment variable (#17830) 2025-05-04 16:27:15 +02:00
Brent Westbrook fe4051b2e6
Fix missing `combine` call for `lint.typing-extensions` setting (#17823)
## Summary

Fixes #17821.

## Test Plan

New CLI test. This might be overkill for such a simple fix, but it made
me feel better to add a test.
2025-05-03 18:19:19 -04:00
Micha Reiser fa628018b2
Use `#[expect(lint)]` over `#[allow(lint)]` where possible (#17822) 2025-05-03 21:20:31 +02:00
Eric Botti 8535af8516
[red-knot] Add support for the LSP diagnostic tag (#17657)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-03 20:35:03 +02:00
Micha Reiser b51c4f82ea
Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
Alex Waygood e6a798b962
[red-knot] Recurse into the types of protocol members when normalizing a protocol's interface (#17808)
## Summary

Currently red-knot does not understand `Foo` and `Bar` here as being
equivalent:

```py
from typing import Protocol

class A: ...
class B: ...
class C: ...

class Foo(Protocol):
    x: A | B | C

class Bar(Protocol):
    x: B | A | C
```

Nor does it understand `A | B | Foo` as being equivalent to `Bar | B |
A`. This PR fixes that.

## Test Plan

new mdtest assertions added that fail on `main`
2025-05-03 16:43:37 +01:00
Alex Waygood 52b0470870
[red-knot] Synthesize a `__call__` attribute for Callable types (#17809)
## Summary

Currently this assertion fails on `main`, because we do not synthesize a
`__call__` attribute for Callable types:

```py
from typing import Protocol, Callable
from knot_extensions import static_assert, is_assignable_to

class Foo(Protocol):
    def __call__(self, x: int, /) -> str: ...

static_assert(is_assignable_to(Callable[[int], str], Foo))
```

This PR fixes that.

See previous discussion about this in
https://github.com/astral-sh/ruff/pull/16493#discussion_r1985098508 and
https://github.com/astral-sh/ruff/pull/17682#issuecomment-2839527750

## Test Plan

Existing mdtests updated; a couple of new ones added.
2025-05-03 16:43:18 +01:00
Brent Westbrook c4a08782cc
Add regression test for parent `noqa` (#17783)
Summary
--

Adds a regression test for #2253 after I tried to delete the fix from
#2464.
2025-05-03 11:38:31 -04:00
Alex Waygood 91481a8be7
[red-knot] Minor simplifications to `types/display.rs` (#17813) 2025-05-03 15:29:05 +01:00
Victor Hugo Gomes 097af060c9
[`refurb`] Fix false positive for float and complex numbers in `FURB116` (#17661) 2025-05-03 15:59:46 +02:00
Alex Waygood b7d0b3f9e5
[red-knot] Add tests asserting that subclasses of `Any` are assignable to arbitrary protocol types (#17810) 2025-05-03 12:41:55 +00:00
Alex Waygood 084352f72c
[red-knot] Distinguish fully static protocols from non-fully-static protocols (#17795) 2025-05-03 11:12:23 +01:00
Carl Meyer 78d4356301
[red-knot] add tracing of salsa events in mdtests (#17803) 2025-05-03 09:00:11 +02:00
Douglas Creager 96697c98f3
[red-knot] Legacy generic classes (#17721)
This adds support for legacy generic classes, which use a
`typing.Generic` base class, or which inherit from another generic class
that has been specialized with legacy typevars.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-02 20:34:20 -04:00
Micha Reiser f7cae4ffb5
[red-knot] Don't panic when `primary-span` is missing while panicking (#17799) 2025-05-02 21:19:03 +01:00
Douglas Creager 675a5af89a
[red-knot] Use `Vec` in `CallArguments`; reuse `self` when we can (#17793)
Quick follow-on to #17788. If there is no bound `self` parameter, we can
reuse the existing `CallArgument{,Type}s`, and we can use a straight
`Vec` instead of a `VecDeque`.
2025-05-02 12:00:02 -04:00
David Peter ea3f4ac059
[red-knot] Refactor: no mutability in call APIs (#17788)
## Summary

Remove mutability in parameter types for a few functions such as
`with_self` and `try_call`. I tried the `Rc`-approach with cheap cloning
[suggest
here](https://github.com/astral-sh/ruff/pull/17733#discussion_r2068722860)
first, but it turns out we need a whole stack of prepended arguments
(there can be [both `self` *and*
`cls`](3cf44e401a/crates/red_knot_python_semantic/resources/mdtest/call/constructor.md?plain=1#L113)),
and we would need the same construct not just for `CallArguments` but
also for `CallArgumentTypes`. At that point we're cloning `VecDeque`s
anyway, so the overhead of cloning the whole `VecDeque` with all
arguments didn't seem to justify the additional code complexity.

## Benchmarks

Benchmarks on tomllib, black, jinja, isort seem neutral.
2025-05-02 13:53:19 +02:00
David Peter 6d2c10cca2
[red-knot] Fix panic for `tuple[x[y]]` string annotation (#17787)
## Summary

closes #17775

## Test Plan

Added corpus regression test
2025-05-02 12:11:47 +02:00
David Peter 3cf44e401a
[red-knot] Implicit instance attributes in generic methods (#17769)
## Summary

Add the ability to detect instance attribute assignments in class
methods that are generic.

This does not address the code duplication mentioned in #16928. I can
open a ticket for this after this has been merged.

closes #16928

## Test Plan

Added regression test.
2025-05-02 08:20:37 +00:00
Micha Reiser 17050e2ec5
doc: Add link to `check-typed-exception` from `S110` and `S112` (#17786) 2025-05-02 09:25:58 +02:00
Micha Reiser a6dc04f96e
Fix module name in ASYNC110, 115, and 116 fixes (#17774) 2025-05-01 23:37:09 +02:00
David Peter e515899141
[red-knot] More informative hover-types for assignments (#17762)
## Summary

closes https://github.com/astral-sh/ruff/issues/17122

## Test Plan

* New hover tests
* Opened the playground locally and saw that new hover-types are shown
as expected.
2025-05-01 20:33:51 +02:00
Abhijeet Prasad Bodas 0c80c56afc
[syntax-errors] Use consistent message for bad starred expression usage. (#17772) 2025-05-01 20:18:35 +02:00
Andrew Gallant b7ce694162 red_knot_server: add auto-completion MVP
This PR does the wiring necessary to respond to completion requests from
LSP clients.

As far as the actual completion results go, they are nearly about the
dumbest and simplest thing we can do: we simply return a de-duplicated
list of all identifiers from the current module.
2025-05-01 12:08:10 -04:00
Brent Westbrook 163d526407
Allow passing a virtual environment to `ruff analyze graph` (#17743)
Summary
--

Fixes #16598 by adding the `--python` flag to `ruff analyze graph`,
which adds a `PythonPath` to the `SearchPathSettings` for module
resolution. For the [albatross-virtual-workspace] example from the uv
repo, this updates the output from the initial issue:

```shell
> ruff analyze graph packages/albatross
{
  "packages/albatross/check_installed_albatross.py": [
    "packages/albatross/src/albatross/__init__.py"
  ],
  "packages/albatross/src/albatross/__init__.py": []
}
```

To include both the the workspace `bird_feeder` import _and_ the
third-party `tqdm` import in the output:

```shell
> myruff analyze graph packages/albatross --python .venv
{
  "packages/albatross/check_installed_albatross.py": [
    "packages/albatross/src/albatross/__init__.py"
  ],
  "packages/albatross/src/albatross/__init__.py": [
    ".venv/lib/python3.12/site-packages/tqdm/__init__.py",
    "packages/bird-feeder/src/bird_feeder/__init__.py"
  ]
}
```

Note the hash in the uv link! I was temporarily very confused why my
local tests were showing an `iniconfig` import instead of `tqdm` until I
realized that the example has been updated on the uv main branch, which
I had locally.

Test Plan
--

A new integration test with a stripped down venv based on the
`albatross` example.

[albatross-virtual-workspace]:
aa629c4a54/scripts/workspaces/albatross-virtual-workspace
2025-05-01 11:29:52 -04:00
Brent Westbrook 75effb8ed7
Bump 0.11.8 (#17766) 2025-05-01 10:19:58 -04:00
Victor Hugo Gomes 3353d07938
[`flake8-use-pathlib`] Fix `PTH104`false positive when `rename` is passed a file descriptor (#17712)
## Summary
Contains the same changes to the semantic type inference as
https://github.com/astral-sh/ruff/pull/17705.

Fixes #17694
<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan

<!-- How was it tested? -->
Snapshot tests.

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
2025-05-01 10:01:17 -04:00
Hans 76ec64d535
[`red-knot`] Allow subclasses of Any to be assignable to Callable types (#17717)
## Summary

Fixes #17701.

## Test plan

New Markdown test.

---------

Co-authored-by: David Peter <mail@david-peter.de>
2025-05-01 10:18:12 +02:00
Micha Reiser b7e69ecbfc
[red-knot] Increase durability of read-only `File` fields (#17757) 2025-05-01 09:25:48 +02:00
Micha Reiser 9c57862262
[red-knot] Cache source type during semanic index building (#17756)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-05-01 08:51:53 +02:00
Victor Hugo Gomes 67ef370733
[`flake8-use-pathlib`] Fix `PTH116` false positive when `stat` is passed a file descriptor (#17709)
Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-05-01 08:16:28 +02:00
github-actions[bot] e17e1e860b
Sync vendored typeshed stubs (#17753)
Co-authored-by: typeshedbot <>
2025-05-01 07:57:03 +02:00
David Peter 03d8679adf
[red-knot] Preliminary `NamedTuple` support (#17738)
## Summary

Adds preliminary support for `NamedTuple`s, including:
* No false positives when constructing a `NamedTuple` object
* Correct signature for the synthesized `__new__` method, i.e. proper
checking of constructor calls
* A patched MRO (`NamedTuple` => `tuple`), mainly to make type inference
of named attributes possible, but also to better reflect the runtime
MRO.

All of this works:
```py
from typing import NamedTuple

class Person(NamedTuple):
    id: int
    name: str
    age: int | None = None

alice = Person(1, "Alice", 42)
alice = Person(id=1, name="Alice", age=42)

reveal_type(alice.id)  # revealed: int
reveal_type(alice.name)  # revealed: str
reveal_type(alice.age)  # revealed: int | None

# error: [missing-argument]
Person(3)

# error: [too-many-positional-arguments]
Person(3, "Eve", 99, "extra")

# error: [invalid-argument-type]
Person(id="3", name="Eve")
```

Not included:
* type inference for index-based access.
* support for the functional `MyTuple = NamedTuple("MyTuple", […])`
syntax

## Test Plan

New Markdown tests

## Ecosystem analysis

```
                          Diagnostic Analysis Report                           
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━┓
┃ Diagnostic ID                     ┃ Severity ┃ Removed ┃ Added ┃ Net Change ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━┩
│ lint:call-non-callable            │ error    │       0 │     3 │         +3 │
│ lint:call-possibly-unbound-method │ warning  │       0 │     4 │         +4 │
│ lint:invalid-argument-type        │ error    │       0 │    72 │        +72 │
│ lint:invalid-context-manager      │ error    │       0 │     2 │         +2 │
│ lint:invalid-return-type          │ error    │       0 │     2 │         +2 │
│ lint:missing-argument             │ error    │       0 │    46 │        +46 │
│ lint:no-matching-overload         │ error    │   19121 │     0 │     -19121 │
│ lint:not-iterable                 │ error    │       0 │     6 │         +6 │
│ lint:possibly-unbound-attribute   │ warning  │      13 │    32 │        +19 │
│ lint:redundant-cast               │ warning  │       0 │     1 │         +1 │
│ lint:unresolved-attribute         │ error    │       0 │    10 │        +10 │
│ lint:unsupported-operator         │ error    │       3 │     9 │         +6 │
│ lint:unused-ignore-comment        │ warning  │      15 │     4 │        -11 │
├───────────────────────────────────┼──────────┼─────────┼───────┼────────────┤
│ TOTAL                             │          │   19152 │   191 │     -18961 │
└───────────────────────────────────┴──────────┴─────────┴───────┴────────────┘

Analysis complete. Found 13 unique diagnostic IDs.
Total diagnostics removed: 19152
Total diagnostics added: 191
Net change: -18961
```

I uploaded the ecosystem full diff (ignoring the 19k
`no-matching-overload` diagnostics)
[here](https://shark.fish/diff-namedtuple.html).

* There are some new `missing-argument` false positives which come from
the fact that named tuples are often created using unpacking as in
`MyNamedTuple(*fields)`, which we do not understand yet.
* There are some new `unresolved-attribute` false positives, because
methods like `_replace` are not available.
* Lots of the `invalid-argument-type` diagnostics look like true
positives

---------

Co-authored-by: Douglas Creager <dcreager@dcreager.net>
2025-04-30 22:52:04 +02:00
Victor Hugo Gomes d33a503686
[red-knot] Add tests for classes that have incompatible `__new__` and `__init__` methods (#17747)
Closes #17737
2025-04-30 20:40:16 +00:00
Dhruv Manilawala d2a238dfad
[red-knot] Update call binding to return all matching overloads (#17618)
## Summary

This PR updates the existing overload matching methods to return an
iterator of all the matched overloads instead.

This would be useful once the overload call evaluation algorithm is
implemented which should provide an accurate picture of all the matched
overloads. The return type would then be picked from either the only
matched overload or the first overload from the ones that are matched.

In an earlier version of this PR, it tried to check if using an
intersection of return types from the matched overload would help reduce
the false positives but that's not enough. [This
comment](https://github.com/astral-sh/ruff/pull/17618#issuecomment-2842891696)
keep the ecosystem analysis for that change for prosperity.

> [!NOTE]
>
> The best way to review this PR is by hiding the whitespace changes
because there are two instances where a large match expression is
indented to be inside a loop over matching overlods
>
> <img width="1207" alt="Screenshot 2025-04-28 at 15 12 16"
src="https://github.com/user-attachments/assets/e06cbfa4-04fa-435f-84ef-4e5c3c5626d1"
/>

## Test Plan

Make sure existing test cases are unaffected and no ecosystem changes.
2025-05-01 01:33:21 +05:30
Wei Lee 6e765b4527
[`airflow`] apply Replacement::AutoImport to `AIR312` (#17570)
## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

This is not yet fixing anything as the names are not changed, but it
lays down the foundation for fixing.

## Test Plan

<!-- How was it tested? -->

the existing test fixture should already cover this change
2025-04-30 15:53:10 -04:00
Vasco Schiavo c5e41c278c
[`ruff`] Add fix safety section (`RUF028`) (#17722)
The PR add the fix safety section for rule `RUF028`
(https://github.com/astral-sh/ruff/issues/15584 )

See also
[here](https://github.com/astral-sh/ruff/issues/15584#issuecomment-2820424485)
for the reason behind the _unsafe_ of the fix.
2025-04-30 15:06:25 -04:00
Abhijeet Prasad Bodas 0eeb02c0c1
[syntax-errors] Detect single starred expression assignment `x = *y` (#17624)
## Summary

Part of #17412

Starred expressions cannot be used as values in assignment expressions.
Add a new semantic syntax error to catch such instances.
Note that we already have
`ParseErrorType::InvalidStarredExpressionUsage` to catch some starred
expression errors during parsing, but that does not cover top level
assignment expressions.

## Test Plan

- Added new inline tests for the new rule
- Found some examples marked as "valid" in existing tests (`_ = *data`),
which are not really valid (per this new rule) and updated them
- There was an existing inline test - `assign_stmt_invalid_value_expr`
which had instances of `*` expression which would be deemed invalid by
this new rule. Converted these to tuples, so that they do not trigger
this new rule.
2025-04-30 15:04:00 -04:00
Brendan Cooley 5679bf00bc
Fix example syntax for pydocstyle ignore_var_parameters option (#17740)
Co-authored-by: Brendan Cooley <brendanc@ladodgers.com>
2025-04-30 18:19:41 +02:00
Alex Waygood b6de01b9a5
[red-knot] Ban direct instantiation of generic protocols as well as non-generic ones (#17741) 2025-04-30 16:01:28 +00:00
David Peter 18bac94226
[red-knot] Lookup of `__new__` (#17733)
## Summary

Model the lookup of `__new__` without going through
`Type::try_call_dunder`. The `__new__` method is only looked up on the
constructed type itself, not on the meta-type.

This now removes ~930 false positives across the ecosystem (vs 255 for
https://github.com/astral-sh/ruff/pull/17662). It introduces 30 new
false positives related to the construction of enums via something like
`Color = enum.Enum("Color", ["RED", "GREEN"])`. This is expected,
because we don't handle custom metaclass `__call__` methods. The fact
that we previously didn't emit diagnostics there was a coincidence (we
incorrectly called `EnumMeta.__new__`, and since we don't fully
understand its signature, that happened to work with `str`, `list`
arguments).

closes #17462

## Test Plan

Regression test
2025-04-30 17:27:09 +02:00
Dhruv Manilawala 7568eeb7a5
[red-knot] Check decorator consistency on overloads (#17684)
## Summary

Part of #15383.

As per the spec
(https://typing.python.org/en/latest/spec/overload.html#invalid-overload-definitions):

For `@staticmethod` and `@classmethod`:

> If one overload signature is decorated with `@staticmethod` or
`@classmethod`, all overload signatures must be similarly decorated. The
implementation, if present, must also have a consistent decorator. Type
checkers should report an error if these conditions are not met.

For `@final` and `@override`:

> If a `@final` or `@override` decorator is supplied for a function with
overloads, the decorator should be applied only to the overload
implementation if it is present. If an overload implementation isn’t
present (for example, in a stub file), the `@final` or `@override`
decorator should be applied only to the first overload. Type checkers
should enforce these rules and generate an error when they are violated.
If a `@final` or `@override` decorator follows these rules, a type
checker should treat the decorator as if it is present on all overloads.

## Test Plan

Update existing tests; add snapshots.
2025-04-30 20:34:21 +05:30
Hans 0e85cbdd91
[`flake8-use-pathlib`] Avoid suggesting `Path.iterdir()` for `os.listdir` with file descriptor (`PTH208`) (#17715)
## Summary

Fixes: #17695

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-04-30 20:08:57 +05:30