@@ -286,7 +286,7 @@ def __getitem__(self, item):
286
286
287
287
def _coerce_to_ndarray (self , force_bool : bool = False ):
288
288
"""
289
- Coerce to an ndarary of object dtype or bool dtype (if force_bool=True).
289
+ Coerce to an ndarray of object dtype or bool dtype (if force_bool=True).
290
290
291
291
Parameters
292
292
----------
@@ -743,9 +743,9 @@ def boolean_arithmetic_method(self, other):
743
743
744
744
745
745
def kleene_or (
746
- left : Union [bool , np .nan , np . ndarray ],
747
- right : Union [bool , np .nan , np . ndarary ],
748
- left_mask : Optional [np .ndarary ],
746
+ left : Union [bool , np .ndarray ],
747
+ right : Union [bool , np .ndarray ],
748
+ left_mask : Optional [np .ndarray ],
749
749
right_mask : Optional [np .ndarray ],
750
750
):
751
751
"""
@@ -772,8 +772,7 @@ def kleene_or(
772
772
if left_mask is None :
773
773
return kleene_or (right , left , right_mask , left_mask )
774
774
775
- assert left_mask is not None
776
- right_is_scalar = right_mask is None
775
+ raise_for_nan (right , method = "or" )
777
776
778
777
mask = left_mask
779
778
@@ -783,11 +782,11 @@ def kleene_or(
783
782
mask = mask .copy ()
784
783
785
784
# handle scalars:
786
- if right_is_scalar and np . isnan ( right ): # TODO(pd .NA): change to NA
787
- result = left .copy ()
788
- mask = left_mask .copy ()
789
- mask [~ result ] = True
790
- return result , mask
785
+ # if right_is_scalar and right is libmissing .NA:
786
+ # result = left.copy()
787
+ # mask = left_mask.copy()
788
+ # mask[~result] = True
789
+ # return result, mask
791
790
792
791
# XXX: verify that this doesn't assume masked values are False!
793
792
result = left | right
@@ -798,9 +797,9 @@ def kleene_or(
798
797
799
798
800
799
def kleene_xor (
801
- left : Union [bool , np .nan , np . ndarray ],
802
- right : Union [bool , np .nan , np . ndarary ],
803
- left_mask : Optional [np .ndarary ],
800
+ left : Union [bool , np .ndarray ],
801
+ right : Union [bool , np .ndarray ],
802
+ left_mask : Optional [np .ndarray ],
804
803
right_mask : Optional [np .ndarray ],
805
804
):
806
805
"""
@@ -826,29 +825,30 @@ def kleene_xor(
826
825
if left_mask is None :
827
826
return kleene_xor (right , left , right_mask , left_mask )
828
827
829
- # Re-use or, and update with adustments.
828
+ raise_for_nan (right , method = "xor" )
829
+ # Re-use or, and update with adjustments.
830
830
result , mask = kleene_or (left , right , left_mask , right_mask )
831
831
832
- # TODO(pd.NA): change to pd.NA
833
- if lib .is_scalar (right ) and right is np . nan :
834
- # True | NA == True
835
- # True ^ NA == NA
836
- mask [result ] = True
837
- else :
838
- # XXX: verify that this doesn't assume masked values are False!
839
- result [left & right ] = False
840
- mask [right & left_mask ] = True
841
- if right_mask is not None :
842
- mask [left & right_mask ] = True
832
+ # # TODO(pd.NA): change to pd.NA
833
+ # if lib.is_scalar(right) and right is libmissing.NA :
834
+ # # True | NA == True
835
+ # # True ^ NA == NA
836
+ # mask[result] = True
837
+
838
+ # XXX: verify that this doesn't assume masked values are False!
839
+ result [left & right ] = False
840
+ mask [right & left_mask ] = True
841
+ if right_mask is not None :
842
+ mask [left & right_mask ] = True
843
843
844
844
result [mask ] = False
845
845
return result , mask
846
846
847
847
848
848
def kleene_and (
849
- left : Union [bool , np .nan , np . ndarray ],
850
- right : Union [bool , np .nan , np . ndarary ],
851
- left_mask : Optional [np .ndarary ],
849
+ left : Union [bool , np .ndarray ],
850
+ right : Union [bool , np .ndarray ],
851
+ left_mask : Optional [np .ndarray ],
852
852
right_mask : Optional [np .ndarray ],
853
853
):
854
854
"""
@@ -871,6 +871,7 @@ def kleene_and(
871
871
if left_mask is None :
872
872
return kleene_and (right , left , right_mask , left_mask )
873
873
874
+ raise_for_nan (right , method = "and" )
874
875
mask = left_mask
875
876
876
877
if right_mask is not None :
@@ -882,6 +883,7 @@ def kleene_and(
882
883
result = left .copy ()
883
884
mask = left_mask .copy ()
884
885
if np .isnan (right ):
886
+ # TODO(pd.NA): change to NA
885
887
mask [result ] = True
886
888
else :
887
889
result = result & right # already copied.
@@ -898,6 +900,11 @@ def kleene_and(
898
900
return result , mask
899
901
900
902
903
+ def raise_for_nan (value , method ):
904
+ if lib .is_scalar (value ) and isinstance (value , float ) and np .isnan (value ):
905
+ raise ValueError (f"Cannot perform logical '{ method } ' with NaN" )
906
+
907
+
901
908
BooleanArray ._add_logical_ops ()
902
909
BooleanArray ._add_comparison_ops ()
903
910
BooleanArray ._add_arithmetic_ops ()
0 commit comments