Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,12 @@ def get_items_list():

def get_items_set():
return tuple({item for item in items}) or None # OK


# https://github.com/astral-sh/ruff/issues/21473
tuple("") or True # OK
Comment thread
ntBre marked this conversation as resolved.
Outdated
tuple(t"") or True # OK
tuple(0) or True # OK
tuple(1) or True # OK
tuple(False) or True # OK
tuple(None) or True # OK
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,12 @@

# https://github.com/astral-sh/ruff/issues/7127
def f(a: "'' and 'b'"): ...


# https://github.com/astral-sh/ruff/issues/21473
tuple("") and False # OK
tuple(t"") and False # OK
tuple(0) and False # OK
tuple(1) and False # OK
tuple(False) and False # OK
tuple(None) and False # OK
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,3 @@ PT015 Assertion always fails, replace with `pytest.fail()`
| ^^^^^^^^^^^^^^^^^
25 | assert tuple("")
|

PT015 Assertion always fails, replace with `pytest.fail()`
--> PT015.py:25:5
|
23 | assert list([])
24 | assert set(set())
25 | assert tuple("")
| ^^^^^^^^^^^^^^^^
26 |
27 | # https://github.com/astral-sh/ruff/issues/19935
|
31 changes: 23 additions & 8 deletions crates/ruff_python_ast/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1322,14 +1322,29 @@ impl Truthiness {
&& arguments.keywords.is_empty()
{
// Ex) `list([1, 2, 3])`
// For tuple(generator), we can't determine statically if the result will
// be empty or not, so return Unknown. The generator itself is truthy, but
// tuple(empty_generator) is falsy. ListComp and SetComp are handled by
// recursing into Self::from_expr below, which returns Unknown for them.
if argument.is_generator_expr() {
Self::Unknown
} else {
Self::from_expr(argument, is_builtin)
// Return Unknown for types with definite truthiness that might result
// in empty iterables or will raise a type error. Explicitly list types
// we recurse for (types without definite truthiness or where Self::from_expr
// correctly handles the truthiness).
match argument {
// Return Unknown for types with definite truthiness that might result
// in empty iterables or will raise a type error:
// - Non-iterable types (numbers, booleans, None, etc.) raise TypeError
// - String types: can't reliably determine truthiness of tuple("") from ""
// (tuple("") creates empty tuple, but tuple("a") creates non-empty tuple)
// - Lambda/Generator: always truthy but might result in empty iterables
Expr::NumberLiteral(_)
| Expr::BooleanLiteral(_)
| Expr::NoneLiteral(_)
| Expr::EllipsisLiteral(_)
| Expr::StringLiteral(_)
Comment thread
ntBre marked this conversation as resolved.
Outdated
| Expr::TString(_)
| Expr::FString(_)
| Expr::BytesLiteral(_)
| Expr::Lambda(_)
| Expr::Generator(_) => Self::Unknown,
// Recurse for all other types - collections, comprehensions, variables, etc.
_ => Self::from_expr(argument, is_builtin),
}
} else {
Self::Unknown
Expand Down