Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

type-comparison (E721) doesn't work when comparing against an actual type #6260

Closed
DetachHead opened this issue Aug 2, 2023 · 7 comments · Fixed by #6325
Closed

type-comparison (E721) doesn't work when comparing against an actual type #6260

DetachHead opened this issue Aug 2, 2023 · 7 comments · Fixed by #6325
Labels
bug Something isn't working rule Implementing or modifying a lint rule

Comments

@DetachHead
Copy link

foo = 1
if type(foo) is int: # no error
    ...
if type(foo) is type(1): # error
    ...

the pylint rule unidiomatic-typecheck catches both cases

@zanieb zanieb added bug Something isn't working rule Implementing or modifying a lint rule labels Aug 2, 2023
charliermarsh added a commit that referenced this issue Aug 4, 2023
## Summary

Extends `type-comparison` to flag:

```python
if type(obj) is int:
    pass
```

In addition to the existing cases, like:

```python
if type(obj) is type(1):
    pass
```

Closes #6260.
@KotlinIsland
Copy link
Contributor

@charliermarsh Could you please clarify if the change here applies to only builtin types? And if so why, because in pylint it applies to any type, not just builtins:

class A: ...
a = A()
type(a) == A  # C0123: Use isinstance() rather than type() for a typecheck. (unidiomatic-typecheck)

@charliermarsh
Copy link
Member

I believe that allowing arbitrary expressions on the right-hand side will lead to false positives for legitimate usages, as in: PyCQA/pycodestyle#882 (comment).

@KotlinIsland
Copy link
Contributor

Oh, is this because Ruff isn't able to tell if the expression on the rhs is a type or not?

@charliermarsh
Copy link
Member

Yes that's correct. E.g., this is contrived but seems reasonable?

type_of_b = type(b)
type(a) is type_of_b

Pylint flags this under unidiomatic-typecheck, but it seems fine to me.

@KotlinIsland
Copy link
Contributor

KotlinIsland commented Aug 4, 2023

Yes that's correct.

If Ruff can't determine if the rhs is a type then I understand that it's better to be less strict here.

E.g., this is contrived but seems reasonable?

type_of_b = type(b)
type(a) is type_of_b

Pylint flags this under unidiomatic-typecheck, but it seems fine to me.

I would write:

type_of_b = type(b)
isinstance(a, type_of_b)

Assuming the context is that I'm just dealing with some kind of usual operation where what I really want is a compatible subtype, and that I don't want to be checking for the exact same type.

Isn't the whole point of the inspection to encourage isinstance over ==/is for types because isinstance is aware of subtypes but ==/is isn't?

class A: ...
class B(A): ...
b = B()
isinstace(b, A)  # True
type(b) == A  # False

@hauntsaninja
Copy link
Contributor

Would you accept a PR with the naive autofix for this?

@charliermarsh
Copy link
Member

Yeah, we can make it a suggested fix.

(Also open to further refinements on the rule logic itself, I’m not certain that our criteria is optimal given above discussion.)

gertvdijk added a commit to gertvdijk/purepythonmilter that referenced this issue Aug 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working rule Implementing or modifying a lint rule
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants