Skip to content

Commit a6f12a0

Browse files
committed
Changed a few test cases to align with kleene principle
1 parent 3492609 commit a6f12a0

File tree

2 files changed

+31
-24
lines changed

2 files changed

+31
-24
lines changed

pandas/core/ops/array_ops.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,10 @@ def na_logical_op(x: np.ndarray, y, op):
390390

391391

392392
def is_nullable_bool(arr) -> bool:
393+
if isinstance(arr, np.ndarray):
394+
if arr.size == 0:
395+
return True
396+
393397
arr = np.asarray(arr, dtype=object).ravel()
394398
# isna works elementwise on object arrays
395399
na_mask = isna(arr)
@@ -550,10 +554,6 @@ def logical_op(left: ArrayLike, right: Any, op) -> ArrayLike:
550554
ndarray or ExtensionArray
551555
"""
552556

553-
bothAreBoolArrays = is_nullable_bool(left) and is_nullable_bool(right)
554-
if bothAreBoolArrays:
555-
return alignOutputWithKleene(left, right, op)
556-
557557
def fill_bool(x, left=None):
558558
# if `left` is specifically not-boolean, we do not cast to bool
559559
if x.dtype.kind in "cfO":
@@ -597,12 +597,15 @@ def fill_bool(x, left=None):
597597
is_other_int_dtype = lib.is_integer(rvalues)
598598

599599
res_values = na_logical_op(lvalues, rvalues, op)
600+
bothAreBoolArrays = is_nullable_bool(left) and is_nullable_bool(right)
601+
# print("Yes both are bools", bothAreBoolArrays)
602+
if bothAreBoolArrays:
603+
return alignOutputWithKleene(left, right, op)
600604

601605
# For int vs int `^`, `|`, `&` are bitwise operators and return
602606
# integer dtypes. Otherwise these are boolean ops
603607
if not (left.dtype.kind in "iu" and is_other_int_dtype):
604608
res_values = fill_bool(res_values)
605-
606609
return res_values
607610

608611

pandas/tests/series/test_logical_ops.py

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,12 @@ def test_logical_operators_bool_dtype_with_empty(self):
3737
index = list("bca")
3838

3939
s_tft = Series([True, False, True], index=index)
40-
s_fff = Series([False, False, False], index=index)
40+
# s_fff = Series([False, False, False], index=index)
4141
s_empty = Series([], dtype=object)
4242

4343
res = s_tft & s_empty
44-
expected = s_fff.sort_index()
44+
# changed the test case output to align with kleene principle
45+
expected = Series([np.nan, False, np.nan], index=index).sort_index()
4546
tm.assert_series_equal(res, expected)
4647

4748
res = s_tft | s_empty
@@ -180,8 +181,8 @@ def test_logical_ops_bool_dtype_with_ndarray(self):
180181
r"Logical ops \(and, or, xor\) between Pandas objects and "
181182
"dtype-less sequences"
182183
)
183-
184-
expected = Series([True, False, False, False, False])
184+
# changed the test case output to align with kleene principle
185+
expected = Series([True, False, np.nan, False, np.nan])
185186
with pytest.raises(TypeError, match=msg):
186187
left & right
187188
result = left & np.array(right)
@@ -200,8 +201,8 @@ def test_logical_ops_bool_dtype_with_ndarray(self):
200201
tm.assert_series_equal(result, expected)
201202
result = left | Series(right)
202203
tm.assert_series_equal(result, expected)
203-
204-
expected = Series([False, True, True, True, True])
204+
# changed the test case output to align with kleene principle
205+
expected = Series([False, True, np.nan, True, np.nan])
205206
with pytest.raises(TypeError, match=msg):
206207
left ^ right
207208
result = left ^ np.array(right)
@@ -368,12 +369,12 @@ def test_logical_ops_label_based(self, using_infer_string):
368369
# rhs is bigger
369370
a = Series([True, False, True], list("bca"))
370371
b = Series([False, True, False, True], list("abcd"))
371-
372-
expected = Series([False, True, False, False], list("abcd"))
372+
# changed the test case output to align with kleene principle
373+
expected = Series([False, True, False, np.nan], list("abcd"))
373374
result = a & b
374375
tm.assert_series_equal(result, expected)
375-
376-
expected = Series([True, True, False, False], list("abcd"))
376+
# changed the test case output to align with kleene principle
377+
expected = Series([True, True, False, True], list("abcd"))
377378
result = a | b
378379
tm.assert_series_equal(result, expected)
379380

@@ -383,7 +384,8 @@ def test_logical_ops_label_based(self, using_infer_string):
383384
empty = Series([], dtype=object)
384385

385386
result = a & empty
386-
expected = Series([False, False, False], list("abc"))
387+
# changed the test case output to align with kleene principle
388+
expected = Series([np.nan, np.nan, False], list("abc"))
387389
tm.assert_series_equal(result, expected)
388390

389391
result = a | empty
@@ -407,7 +409,9 @@ def test_logical_ops_label_based(self, using_infer_string):
407409
Series(np.nan, b.index),
408410
Series(np.nan, a.index),
409411
]:
410-
result = a[a | e]
412+
result = a[(a | e).astype("boolean")]
413+
# cast to boolean because object dtype with nan
414+
# cannot be compared to True
411415
tm.assert_series_equal(result, a[a])
412416

413417
for e in [Series(["z"])]:
@@ -459,16 +463,16 @@ def test_logical_ops_df_compat(self):
459463
# GH#1134
460464
s1 = Series([True, False, True], index=list("ABC"), name="x")
461465
s2 = Series([True, True, False], index=list("ABD"), name="x")
462-
463-
exp = Series([True, False, False, False], index=list("ABCD"), name="x")
466+
# changed the test case output to align with kleene principle
467+
exp = Series([True, False, np.nan, False], index=list("ABCD"), name="x")
464468
tm.assert_series_equal(s1 & s2, exp)
465469
tm.assert_series_equal(s2 & s1, exp)
466470

467471
# True | np.nan => True
468472
exp_or1 = Series([True, True, True, False], index=list("ABCD"), name="x")
469473
tm.assert_series_equal(s1 | s2, exp_or1)
470-
# np.nan | True => np.nan, filled with False
471-
exp_or = Series([True, True, False, False], index=list("ABCD"), name="x")
474+
# np.nan | True => True (should be)
475+
exp_or = Series([True, True, True, False], index=list("ABCD"), name="x")
472476
tm.assert_series_equal(s2 | s1, exp_or)
473477

474478
# DataFrame doesn't fill nan with False
@@ -482,13 +486,13 @@ def test_logical_ops_df_compat(self):
482486
# different length
483487
s3 = Series([True, False, True], index=list("ABC"), name="x")
484488
s4 = Series([True, True, True, True], index=list("ABCD"), name="x")
485-
486-
exp = Series([True, False, True, False], index=list("ABCD"), name="x")
489+
# changed the test case output to align with kleene principle
490+
exp = Series([True, False, True, np.nan], index=list("ABCD"), name="x")
487491
tm.assert_series_equal(s3 & s4, exp)
488492
tm.assert_series_equal(s4 & s3, exp)
489493

490494
# np.nan | True => np.nan, filled with False
491-
exp_or1 = Series([True, True, True, False], index=list("ABCD"), name="x")
495+
exp_or1 = Series([True, True, True, True], index=list("ABCD"), name="x")
492496
tm.assert_series_equal(s3 | s4, exp_or1)
493497
# True | np.nan => True
494498
exp_or = Series([True, True, True, True], index=list("ABCD"), name="x")

0 commit comments

Comments
 (0)