code: def mask_cmp_op(x, y, op, allowed_types):
      
      # TODO: Can we make the allowed_types arg unnecessary?
      xrav = x.ravel()
      result = np.empty(x.size, dtype=bool)
      if isinstance(y, allowed_types):
          yrav = y.ravel()
          mask = notna(xrav) & notna(yrav)
          result[mask] = op(np.array(list(xrav[mask])),
                            np.array(list(yrav[mask])))
      else:
          mask = notna(xrav)
          result[mask] = op(np.array(list(xrav[mask])), y)
  
      if op == operator.ne:  # pragma: no cover
          np.putmask(result, ~mask, True)
      else:
          np.putmask(result, ~mask, False)
      result = result.reshape(x.shape)
      return result
docs: Apply the function `op` to only non-null points in x and y.
  
      Parameters
      ----------
      x : array-like
      y : array-like
      op : binary operation
      allowed_types : class or tuple of classes
  
      Returns
      -------
      result : ndarray[bool]