summaryrefslogtreecommitdiff
path: root/numpy/lib
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/lib')
-rw-r--r--numpy/lib/npyio.py13
-rw-r--r--numpy/lib/tests/test_loadtxt.py50
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)