diff options
Diffstat (limited to 'numpy/lib')
| -rw-r--r-- | numpy/lib/npyio.py | 13 | ||||
| -rw-r--r-- | numpy/lib/tests/test_loadtxt.py | 50 |
2 files changed, 57 insertions, 6 deletions
diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py index 62d00cfb9..be313d104 100644 --- a/numpy/lib/npyio.py +++ b/numpy/lib/npyio.py @@ -920,12 +920,6 @@ def _read(fname, *, delimiter=',', comment='#', quote='"', if comment is None: comments = None - elif isinstance(comment, str): - if len(comment) > 1: # length of 0 is rejected later - comments = (comment,) - comment = None - else: - comments = None else: # assume comments are a sequence of strings comments = tuple(comment) @@ -938,6 +932,13 @@ def _read(fname, *, delimiter=',', comment='#', quote='"', if isinstance(comments[0], str) and len(comments[0]) == 1: comment = comments[0] comments = None + else: + # Input validation if there are multiple comment characters + if delimiter in comments: + raise TypeError( + f"Comment characters '{comments}' cannot include the " + f"delimiter '{delimiter}'" + ) # comment is now either a 1 or 0 character string or a tuple: if comments is not None: diff --git a/numpy/lib/tests/test_loadtxt.py b/numpy/lib/tests/test_loadtxt.py index c5a14ed46..2038bfc85 100644 --- a/numpy/lib/tests/test_loadtxt.py +++ b/numpy/lib/tests/test_loadtxt.py @@ -876,3 +876,53 @@ class TestCReaderUnitTests: data, dtype=np.dtype("U10"), filelike=True, quote='"', comment="#", skiplines=1) assert_array_equal(res[:, 0], ["1", f"2{newline}", "3", "4 "]) + + +def test_delimiter_comment_collision_raises(): + with pytest.raises(TypeError, match="control characters.*are identical"): + np.loadtxt(StringIO("1, 2, 3"), delimiter=",", comments=",") + + +def test_delimiter_quotechar_collision_raises(): + with pytest.raises(TypeError, match="control characters.*are identical"): + np.loadtxt(StringIO("1, 2, 3"), delimiter=",", quotechar=",") + + +def test_comment_quotechar_collision_raises(): + with pytest.raises(TypeError, match="control characters.*are identical"): + np.loadtxt(StringIO("1 2 3"), comments="#", quotechar="#") + + +def test_delimiter_and_multiple_comments_collision_raises(): + with pytest.raises( + TypeError, match="Comment characters.*cannot include the delimiter" + ): + np.loadtxt(StringIO("1, 2, 3"), delimiter=",", comments=["#", ","]) + + +@pytest.mark.parametrize( + "ws", + ( + " ", # space + "\t", # tab + "\u2003", # em + "\u00A0", # non-break + "\u3000", # ideographic space + ) +) +def test_collision_with_default_delimiter_raises(ws): + with pytest.raises(TypeError, match="control characters.*are identical"): + np.loadtxt(StringIO(f"1{ws}2{ws}3\n4{ws}5{ws}6\n"), comments=ws) + with pytest.raises(TypeError, match="control characters.*are identical"): + np.loadtxt(StringIO(f"1{ws}2{ws}3\n4{ws}5{ws}6\n"), quotechar=ws) + + +@pytest.mark.parametrize("nl", ("\n", "\r")) +def test_control_character_newline_raises(nl): + txt = StringIO(f"1{nl}2{nl}3{nl}{nl}4{nl}5{nl}6{nl}{nl}") + with pytest.raises(TypeError, match="control character.*cannot be a newline"): + np.loadtxt(txt, delimiter=nl) + with pytest.raises(TypeError, match="control character.*cannot be a newline"): + np.loadtxt(txt, comments=nl) + with pytest.raises(TypeError, match="control character.*cannot be a newline"): + np.loadtxt(txt, quotechar=nl) |
