From 950e0bf9fe51dfe45af4eb98bc9ae247aa13bb97 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Tue, 11 Feb 2020 21:20:57 -0600 Subject: [PATCH 1/9] Add test --- .../tests/util/test_assert_numpy_array_equal.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/pandas/tests/util/test_assert_numpy_array_equal.py b/pandas/tests/util/test_assert_numpy_array_equal.py index c8ae9ebdd8651..c39ada0a75331 100644 --- a/pandas/tests/util/test_assert_numpy_array_equal.py +++ b/pandas/tests/util/test_assert_numpy_array_equal.py @@ -1,6 +1,8 @@ import numpy as np import pytest +from pandas._libs.missing import NA + from pandas import Timestamp import pandas._testing as tm @@ -175,3 +177,18 @@ def test_numpy_array_equal_copy_flag(other_type, check_same): tm.assert_numpy_array_equal(a, other, check_same=check_same) else: tm.assert_numpy_array_equal(a, other, check_same=check_same) + + +def test_numpy_array_equal_contains_na(): + # https://github.com/pandas-dev/pandas/issues/31881 + a = np.array([True, False]) + b = np.array([True, NA]) + + msg = """numpy array are different + +numpy array values are different \\(50.0 %\\) +\\[left\\]: \\[True, False\\] +\\[right\\]: \\[True, \\]""" + + with pytest.raises(AssertionError, match=msg): + tm.assert_numpy_array_equal(a, b) From cd86d6a06d79630bd49115ece942eae10df6d76f Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Tue, 11 Feb 2020 21:21:31 -0600 Subject: [PATCH 2/9] Handle NA in assert_numpy_array_equal --- pandas/_libs/lib.pyx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pandas/_libs/lib.pyx b/pandas/_libs/lib.pyx index 9702eb4615909..30b0bb5d2660c 100644 --- a/pandas/_libs/lib.pyx +++ b/pandas/_libs/lib.pyx @@ -571,6 +571,11 @@ def array_equivalent_object(left: object[:], right: object[:]) -> bool: if PyArray_Check(x) and PyArray_Check(y): if not array_equivalent_object(x, y): return False + elif x is C_NA or y is C_NA: + if x is C_NA and y is C_NA: + return True + else: + return False elif not (PyObject_RichCompareBool(x, y, Py_EQ) or (x is None or is_nan(x)) and (y is None or is_nan(y))): return False From 8f7e719fed4db6edf550350bf4af47867bd6cc8b Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Tue, 11 Feb 2020 21:28:21 -0600 Subject: [PATCH 3/9] Add whatsnew --- doc/source/whatsnew/v1.0.2.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/source/whatsnew/v1.0.2.rst b/doc/source/whatsnew/v1.0.2.rst index f4bb8c580fb08..d74f89b93efc3 100644 --- a/doc/source/whatsnew/v1.0.2.rst +++ b/doc/source/whatsnew/v1.0.2.rst @@ -32,6 +32,10 @@ Bug fixes - Using ``pd.NA`` with :meth:`DataFrame.to_json` now correctly outputs a null value instead of an empty object (:issue:`31615`) +**Testing** + +- Fixed bug where :meth:`assert_numpy_array_equal` would raise a ``TypeError`` when encountering ``pd.NA`` (:issue:`31881`) + .. --------------------------------------------------------------------------- .. _whatsnew_102.contributors: From 5c6a742d66a0f7460142cf94b5f60ef1fedd2b49 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Wed, 12 Feb 2020 08:05:51 -0600 Subject: [PATCH 4/9] Revert "Add whatsnew" This reverts commit 8f7e719fed4db6edf550350bf4af47867bd6cc8b. --- doc/source/whatsnew/v1.0.2.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/source/whatsnew/v1.0.2.rst b/doc/source/whatsnew/v1.0.2.rst index d74f89b93efc3..f4bb8c580fb08 100644 --- a/doc/source/whatsnew/v1.0.2.rst +++ b/doc/source/whatsnew/v1.0.2.rst @@ -32,10 +32,6 @@ Bug fixes - Using ``pd.NA`` with :meth:`DataFrame.to_json` now correctly outputs a null value instead of an empty object (:issue:`31615`) -**Testing** - -- Fixed bug where :meth:`assert_numpy_array_equal` would raise a ``TypeError`` when encountering ``pd.NA`` (:issue:`31881`) - .. --------------------------------------------------------------------------- .. _whatsnew_102.contributors: From d006a56856256aecc514ecbadfd38c305d34ff53 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Wed, 12 Feb 2020 08:11:50 -0600 Subject: [PATCH 5/9] Use xor --- pandas/_libs/lib.pyx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pandas/_libs/lib.pyx b/pandas/_libs/lib.pyx index 30b0bb5d2660c..eaa73c00705ea 100644 --- a/pandas/_libs/lib.pyx +++ b/pandas/_libs/lib.pyx @@ -571,11 +571,8 @@ def array_equivalent_object(left: object[:], right: object[:]) -> bool: if PyArray_Check(x) and PyArray_Check(y): if not array_equivalent_object(x, y): return False - elif x is C_NA or y is C_NA: - if x is C_NA and y is C_NA: - return True - else: - return False + elif (x is C_NA) ^ (y is C_NA): + return False elif not (PyObject_RichCompareBool(x, y, Py_EQ) or (x is None or is_nan(x)) and (y is None or is_nan(y))): return False From 8d5a49a68bcbc8df31e20a82580ac7bc23aff82e Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Wed, 12 Feb 2020 08:19:54 -0600 Subject: [PATCH 6/9] Add identical NA test --- pandas/tests/util/test_assert_numpy_array_equal.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pandas/tests/util/test_assert_numpy_array_equal.py b/pandas/tests/util/test_assert_numpy_array_equal.py index c39ada0a75331..8ac59d59caeda 100644 --- a/pandas/tests/util/test_assert_numpy_array_equal.py +++ b/pandas/tests/util/test_assert_numpy_array_equal.py @@ -192,3 +192,9 @@ def test_numpy_array_equal_contains_na(): with pytest.raises(AssertionError, match=msg): tm.assert_numpy_array_equal(a, b) + + +def test_numpy_array_equal_identical_na(nulls_fixture): + a = np.array([nulls_fixture]) + + tm.assert_numpy_array_equal(a, a) From 6905a59401fc0693291c86df3cefb80056c88dea Mon Sep 17 00:00:00 2001 From: Daniel Saxton <2658661+dsaxton@users.noreply.github.com> Date: Wed, 12 Feb 2020 09:09:43 -0600 Subject: [PATCH 7/9] Update pandas/tests/util/test_assert_numpy_array_equal.py Co-Authored-By: Joris Van den Bossche --- pandas/tests/util/test_assert_numpy_array_equal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/util/test_assert_numpy_array_equal.py b/pandas/tests/util/test_assert_numpy_array_equal.py index 8ac59d59caeda..2f283e823546b 100644 --- a/pandas/tests/util/test_assert_numpy_array_equal.py +++ b/pandas/tests/util/test_assert_numpy_array_equal.py @@ -195,6 +195,6 @@ def test_numpy_array_equal_contains_na(): def test_numpy_array_equal_identical_na(nulls_fixture): - a = np.array([nulls_fixture]) + a = np.array([nulls_fixture], dtype=object) tm.assert_numpy_array_equal(a, a) From 9c4f3ed016e844e030f0506a8a344e0c14e0c029 Mon Sep 17 00:00:00 2001 From: Daniel Saxton <2658661+dsaxton@users.noreply.github.com> Date: Wed, 12 Feb 2020 09:09:50 -0600 Subject: [PATCH 8/9] Update pandas/tests/util/test_assert_numpy_array_equal.py Co-Authored-By: Joris Van den Bossche --- pandas/tests/util/test_assert_numpy_array_equal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/util/test_assert_numpy_array_equal.py b/pandas/tests/util/test_assert_numpy_array_equal.py index 2f283e823546b..54f0982616edd 100644 --- a/pandas/tests/util/test_assert_numpy_array_equal.py +++ b/pandas/tests/util/test_assert_numpy_array_equal.py @@ -182,7 +182,7 @@ def test_numpy_array_equal_copy_flag(other_type, check_same): def test_numpy_array_equal_contains_na(): # https://github.com/pandas-dev/pandas/issues/31881 a = np.array([True, False]) - b = np.array([True, NA]) + b = np.array([True, NA], dtype=object) msg = """numpy array are different From 9ee33c80e0caaff76c0de6087b2ee8efb772df12 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Wed, 12 Feb 2020 09:28:18 -0600 Subject: [PATCH 9/9] Add unequal NA test --- .../util/test_assert_numpy_array_equal.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/pandas/tests/util/test_assert_numpy_array_equal.py b/pandas/tests/util/test_assert_numpy_array_equal.py index 54f0982616edd..d29ddedd2fdd6 100644 --- a/pandas/tests/util/test_assert_numpy_array_equal.py +++ b/pandas/tests/util/test_assert_numpy_array_equal.py @@ -1,8 +1,7 @@ import numpy as np import pytest -from pandas._libs.missing import NA - +import pandas as pd from pandas import Timestamp import pandas._testing as tm @@ -182,7 +181,7 @@ def test_numpy_array_equal_copy_flag(other_type, check_same): def test_numpy_array_equal_contains_na(): # https://github.com/pandas-dev/pandas/issues/31881 a = np.array([True, False]) - b = np.array([True, NA], dtype=object) + b = np.array([True, pd.NA], dtype=object) msg = """numpy array are different @@ -198,3 +197,17 @@ def test_numpy_array_equal_identical_na(nulls_fixture): a = np.array([nulls_fixture], dtype=object) tm.assert_numpy_array_equal(a, a) + + +def test_numpy_array_equal_different_na(): + a = np.array([np.nan], dtype=object) + b = np.array([pd.NA], dtype=object) + + msg = """numpy array are different + +numpy array values are different \\(100.0 %\\) +\\[left\\]: \\[nan\\] +\\[right\\]: \\[\\]""" + + with pytest.raises(AssertionError, match=msg): + tm.assert_numpy_array_equal(a, b)