|
10 | 10 | PyperclipWindowsException,
|
11 | 11 | )
|
12 | 12 |
|
| 13 | +import pandas as pd |
13 | 14 | from pandas import (
|
| 15 | + NA, |
14 | 16 | DataFrame,
|
| 17 | + Series, |
15 | 18 | get_option,
|
16 | 19 | read_clipboard,
|
17 | 20 | )
|
18 | 21 | import pandas._testing as tm
|
| 22 | +from pandas.core.arrays import ( |
| 23 | + ArrowStringArray, |
| 24 | + StringArray, |
| 25 | +) |
19 | 26 |
|
20 | 27 | from pandas.io.clipboard import (
|
21 | 28 | CheckedCall,
|
@@ -402,3 +409,60 @@ def test_raw_roundtrip(self, data):
|
402 | 409 | # PR #25040 wide unicode wasn't copied correctly on PY3 on windows
|
403 | 410 | clipboard_set(data)
|
404 | 411 | assert data == clipboard_get()
|
| 412 | + |
| 413 | + @pytest.mark.parametrize("dtype_backend", ["pandas", "pyarrow"]) |
| 414 | + @pytest.mark.parametrize("engine", ["c", "python"]) |
| 415 | + def test_read_clipboard_nullable_dtypes( |
| 416 | + self, request, mock_clipboard, string_storage, dtype_backend, engine |
| 417 | + ): |
| 418 | + # GH#50502 |
| 419 | + if string_storage == "pyarrow" or dtype_backend == "pyarrow": |
| 420 | + pa = pytest.importorskip("pyarrow") |
| 421 | + |
| 422 | + if dtype_backend == "pyarrow" and engine == "c": |
| 423 | + pytest.skip(reason="c engine not yet supported") |
| 424 | + |
| 425 | + if string_storage == "python": |
| 426 | + string_array = StringArray(np.array(["x", "y"], dtype=np.object_)) |
| 427 | + string_array_na = StringArray(np.array(["x", NA], dtype=np.object_)) |
| 428 | + |
| 429 | + else: |
| 430 | + string_array = ArrowStringArray(pa.array(["x", "y"])) |
| 431 | + string_array_na = ArrowStringArray(pa.array(["x", None])) |
| 432 | + |
| 433 | + text = """a,b,c,d,e,f,g,h,i |
| 434 | +x,1,4.0,x,2,4.0,,True,False |
| 435 | +y,2,5.0,,,,,False,""" |
| 436 | + mock_clipboard[request.node.name] = text |
| 437 | + |
| 438 | + with pd.option_context("mode.string_storage", string_storage): |
| 439 | + with pd.option_context("mode.dtype_backend", dtype_backend): |
| 440 | + result = read_clipboard( |
| 441 | + sep=",", use_nullable_dtypes=True, engine=engine |
| 442 | + ) |
| 443 | + |
| 444 | + expected = DataFrame( |
| 445 | + { |
| 446 | + "a": string_array, |
| 447 | + "b": Series([1, 2], dtype="Int64"), |
| 448 | + "c": Series([4.0, 5.0], dtype="Float64"), |
| 449 | + "d": string_array_na, |
| 450 | + "e": Series([2, NA], dtype="Int64"), |
| 451 | + "f": Series([4.0, NA], dtype="Float64"), |
| 452 | + "g": Series([NA, NA], dtype="Int64"), |
| 453 | + "h": Series([True, False], dtype="boolean"), |
| 454 | + "i": Series([False, NA], dtype="boolean"), |
| 455 | + } |
| 456 | + ) |
| 457 | + if dtype_backend == "pyarrow": |
| 458 | + from pandas.arrays import ArrowExtensionArray |
| 459 | + |
| 460 | + expected = DataFrame( |
| 461 | + { |
| 462 | + col: ArrowExtensionArray(pa.array(expected[col], from_pandas=True)) |
| 463 | + for col in expected.columns |
| 464 | + } |
| 465 | + ) |
| 466 | + expected["g"] = ArrowExtensionArray(pa.array([None, None])) |
| 467 | + |
| 468 | + tm.assert_frame_equal(result, expected) |
0 commit comments