[refurb] Add coverage for using set(...) in single-item-membership-test (FURB171)#15793
Conversation
77168c6 to
781af24
Compare
|
|
Ah, I see, it doesn't work if the single argument to |
AlexWaygood
left a comment
There was a problem hiding this comment.
Thanks! However, I think it would be incorrect for this rule to trigger on set(1), since that doesn't create a set with a single member at runtime. It raises an exception.
| if 1 in set(1): | ||
| print("Single-element set") |
There was a problem hiding this comment.
hmm, this fails at runtime:
>>> set(1)
Traceback (most recent call last):
File "<python-input-0>", line 1, in <module>
set(1)
~~~^^^
TypeError: 'int' object is not iterable| if 1 in set(1, 2): | ||
| pass |
There was a problem hiding this comment.
this also fails at runtime:
>>> set(1, 2)
Traceback (most recent call last):
File "<python-input-1>", line 1, in <module>
set(1, 2)
~~~^^^^^^
TypeError: set expected at most 1 argument, got 2|
To clarify, @naslundx, all of these succeed at runtime, and I'd be okay with adding support for these to set([1])
set((1,))
set({1})You'd need to check that the object being passed to the |
Additionally, that element should be literal/hashable, so that errors like this one are not masked: if a in set([{}]): ... # TypeError: unhashable type: 'dict'
if a == {}: ... # No errors |
I think we should open a separate issue about this because that behavior is already present in the current scope of the rule: 1 in {set()} # TypeError: unhashable type: 'set'
1 == set() # No errors |
refurb] Add coverage for using set(...) in single-item-membership-test (FURB171)
|
Maybe check for frozenset([1])
frozenset((1,))
frozenset({1}) |
|
I did not see the updated comments on this PR - I will bring it back up to speed. Thanks for comments! |
…ItemMembershipTest
781af24 to
ffc2c83
Compare
dylwil3
left a comment
There was a problem hiding this comment.
Looking good, thank you! Let's add a little more test coverage, and handle the case where someone is shadowing or explicitly importing the builtin.
| if let Expr::Name(ast::ExprName { | ||
| id, | ||
| ctx: _, | ||
| range: _, | ||
| }) = func.as_ref() | ||
| { | ||
| if (id == "set" || id == "frozenset") && arguments.args.len() == 1 { | ||
| return single_item(&arguments.args[0]); | ||
| } | ||
| } |
There was a problem hiding this comment.
You should use this method to make sure the function matches the builtin that you expect:
ruff/crates/ruff_python_semantic/src/model.rs
Lines 316 to 319 in d94a78a
There was a problem hiding this comment.
Did not know about this, that's great!
| if 1 in set({1}): | ||
| print("Single-element set") | ||
|
|
There was a problem hiding this comment.
Could you add some examples with nested calls to set/frozenset since your implementation is recursive? Like
set(set([1]))Also a few non-examples, like:
set(1,) # this is a TypeError so we shouldn't do anything with it
set(1,2) # this is also a TypeError
set((x for x in range(2))) # this is legal but not one element|
Thanks @naslundx for working on this. I'll close this PR because it has become stale. For anyone interested, feel free to open a new PR implementing this change, incorporating the feedback from this review. |
|
A little late to the party but I made the fixes, and will put up an updated PR |
…18035) ## Summary Adds coverage of using set(...) in addition to `{...} in SingleItemMembershipTest. Fixes #15792 (and replaces the old PR #15793) <!-- What's the purpose of the change? What does it do, and why? --> ## Test Plan Updated unit test and snapshot. Steps to reproduce are in the issue linked above. <!-- How was it tested? -->
Summary
Adds coverage of using
set(...)in addition to `{...} in SingleItemMembershipTest.Fixes #15792
Test Plan
Updated unit test and snapshot.
Steps to reproduce are in the issue linked above.