about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--r_qtl/r_qtl2.py35
-rw-r--r--tests/r_qtl/test_files/nonexistent.zipbin0 -> 380 bytes
-rw-r--r--tests/r_qtl/test_r_qtl2_nonexistent_file.py29
3 files changed, 48 insertions, 16 deletions
diff --git a/r_qtl/r_qtl2.py b/r_qtl/r_qtl2.py
index a8958a0..d3a3805 100644
--- a/r_qtl/r_qtl2.py
+++ b/r_qtl/r_qtl2.py
@@ -189,23 +189,26 @@ def file_data(zfile: ZipFile,
                   [str, tuple[str, ...], tuple[str, ...]],
                   tuple[dict, ...]] = __default_process_value_transposed__) -> Iterator[dict]:
     """Load data from files in R/qtl2 zip bundle."""
-    if isinstance(cdata[member_key], list):
-        for row in (line for lines in
-                    (file_data(
-                        zfile, member_key, {**cdata, member_key: innerfile},
-                        process_value, process_transposed_value)
-                     for innerfile in cdata[member_key])
-                    for line in lines):
-            yield row
-        return
-    if not cdata.get(f"{member_key}_transposed", False):
-        for row in with_non_transposed(zfile, member_key, cdata, process_value):
-            yield row
-        return
+    try:
+        if isinstance(cdata[member_key], list):
+            for row in (line for lines in
+                        (file_data(
+                            zfile, member_key, {**cdata, member_key: innerfile},
+                            process_value, process_transposed_value)
+                         for innerfile in cdata[member_key])
+                        for line in lines):
+                yield row
+            return
+        if not cdata.get(f"{member_key}_transposed", False):
+            for row in with_non_transposed(zfile, member_key, cdata, process_value):
+                yield row
+            return
 
-    for row in with_transposed(
-            zfile, member_key, cdata, process_transposed_value):
-        yield row
+        for row in with_transposed(
+                zfile, member_key, cdata, process_transposed_value):
+            yield row
+    except KeyError as exc:
+        raise InvalidFormat(*exc.args) from exc
 
 def cross_information(zfile: ZipFile, cdata: dict) -> Iterator[dict]:
     """Load cross information where present."""
diff --git a/tests/r_qtl/test_files/nonexistent.zip b/tests/r_qtl/test_files/nonexistent.zip
new file mode 100644
index 0000000..4a31bf1
--- /dev/null
+++ b/tests/r_qtl/test_files/nonexistent.zip
Binary files differdiff --git a/tests/r_qtl/test_r_qtl2_nonexistent_file.py b/tests/r_qtl/test_r_qtl2_nonexistent_file.py
new file mode 100644
index 0000000..c783a76
--- /dev/null
+++ b/tests/r_qtl/test_r_qtl2_nonexistent_file.py
@@ -0,0 +1,29 @@
+"""Test accessing nonexistent member."""
+from pathlib import Path
+
+import pytest
+from zipfile import ZipFile
+
+from r_qtl import r_qtl2 as rqtl2
+
+@pytest.mark.unit_test
+@pytest.mark.parametrize(
+    "filepath,memberkey",
+    (("tests/r_qtl/test_files/nonexistent.zip", "geno"),
+     ("tests/r_qtl/test_files/nonexistent.zip", "founder_geno"),
+     ("tests/r_qtl/test_files/nonexistent.zip", "pheno"),
+     ("tests/r_qtl/test_files/nonexistent.zip", "covar"),
+     ("tests/r_qtl/test_files/nonexistent.zip", "phenocovar"),
+     ("tests/r_qtl/test_files/nonexistent.zip", "gmap"),
+     ("tests/r_qtl/test_files/nonexistent.zip", "pmap")))
+def test_loading_nonexistent_file(filepath, memberkey):
+    """
+    GIVEN: A zipfile with a valid control file, but some files mentioned in the
+        control file do not exist in the zipfile
+    WHEN: access is made to such missing files
+    THEN: raise an exception
+    """
+    with (ZipFile(Path(filepath).absolute(), "r") as zfile,
+          pytest.raises(rqtl2.InvalidFormat)):
+        cdata = rqtl2.control_data(zfile)
+        tuple(rqtl2.file_data(zfile, memberkey, cdata))