@@ -286,7 +286,7 @@ def __getitem__(self, item):
286286
287287 def _coerce_to_ndarray (self , force_bool : bool = False ):
288288 """
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).
290290
291291 Parameters
292292 ----------
@@ -743,9 +743,9 @@ def boolean_arithmetic_method(self, other):
743743
744744
745745def 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 ],
749749 right_mask : Optional [np .ndarray ],
750750):
751751 """
@@ -772,8 +772,7 @@ def kleene_or(
772772 if left_mask is None :
773773 return kleene_or (right , left , right_mask , left_mask )
774774
775- assert left_mask is not None
776- right_is_scalar = right_mask is None
775+ raise_for_nan (right , method = "or" )
777776
778777 mask = left_mask
779778
@@ -783,11 +782,11 @@ def kleene_or(
783782 mask = mask .copy ()
784783
785784 # 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
791790
792791 # XXX: verify that this doesn't assume masked values are False!
793792 result = left | right
@@ -798,9 +797,9 @@ def kleene_or(
798797
799798
800799def 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 ],
804803 right_mask : Optional [np .ndarray ],
805804):
806805 """
@@ -826,29 +825,30 @@ def kleene_xor(
826825 if left_mask is None :
827826 return kleene_xor (right , left , right_mask , left_mask )
828827
829- # Re-use or, and update with adustments.
828+ raise_for_nan (right , method = "xor" )
829+ # Re-use or, and update with adjustments.
830830 result , mask = kleene_or (left , right , left_mask , right_mask )
831831
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
843843
844844 result [mask ] = False
845845 return result , mask
846846
847847
848848def 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 ],
852852 right_mask : Optional [np .ndarray ],
853853):
854854 """
@@ -871,6 +871,7 @@ def kleene_and(
871871 if left_mask is None :
872872 return kleene_and (right , left , right_mask , left_mask )
873873
874+ raise_for_nan (right , method = "and" )
874875 mask = left_mask
875876
876877 if right_mask is not None :
@@ -882,6 +883,7 @@ def kleene_and(
882883 result = left .copy ()
883884 mask = left_mask .copy ()
884885 if np .isnan (right ):
886+ # TODO(pd.NA): change to NA
885887 mask [result ] = True
886888 else :
887889 result = result & right # already copied.
@@ -898,6 +900,11 @@ def kleene_and(
898900 return result , mask
899901
900902
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+
901908BooleanArray ._add_logical_ops ()
902909BooleanArray ._add_comparison_ops ()
903910BooleanArray ._add_arithmetic_ops ()
0 commit comments