Repository: cogent3/cogent3
Pull request #1066 (2022-06-29 02:36:17)

TST: refactory io tests to using pytest
[CHANGED] test_io.py now uses pytest, not unittest. Have taken advantage of
    parameterize to simplify evaluating different test conditions.

[CHANGED] made open_url and open_ default to the same reading mode

[NEW] the io.open functions now handle case where mode=None


Patch:
diff --git a/src/cogent3/util/io.py b/src/cogent3/util/io.py
index 67548ff98..bc84d69c4 100644
--- a/src/cogent3/util/io.py
+++ b/src/cogent3/util/io.py
@@ -3,16 +3,15 @@ import uuid
 
 from bz2 import open as bzip_open
 from gzip import open as gzip_open
+from io import TextIOWrapper
 from os import path as os_path
 from os import remove
 from pathlib import Path
 from tempfile import mkdtemp
 from typing import Union
-from zipfile import ZipFile
-from urllib.parse import ParseResult
-from io import TextIOWrapper
+from urllib.parse import ParseResult, urlparse
 from urllib.request import urlopen
-from urllib.parse import urlparse
+from zipfile import ZipFile
 
 from chardet import detect
 
@@ -42,8 +41,7 @@ def open_zip(filename: Union[str, Path], mode="r", **kwargs):
     """
     # import of standard library io module as some code quality tools
     # confuse this with a circular import
-    from io import TextIOWrapper
-
+    mode = mode or "r"
     binary_mode = "b" in mode
     mode = mode[:1]
 
@@ -66,7 +64,7 @@ def open_zip(filename: Union[str, Path], mode="r", **kwargs):
 
 def open_(filename: Union[str, Path], mode="rt", **kwargs):
     """open that handles different compression"""
-
+    mode = mode or "rt"
     filename = Path(filename).expanduser().absolute()
     op = {".gz": gzip_open, ".bz2": bzip_open, ".zip": open_zip}.get(
         filename.suffix, open
@@ -85,7 +83,7 @@ def open_(filename: Union[str, Path], mode="rt", **kwargs):
     return op(filename, mode, encoding=encoding, **kwargs)
 
 
-def open_url(url: Union[str, ParseResult], mode="rb", **kwargs):
+def open_url(url: Union[str, ParseResult], mode="r", **kwargs):
     """open a url
 
     Parameters
@@ -93,18 +91,22 @@ def open_url(url: Union[str, ParseResult], mode="rb", **kwargs):
     url : urllib.parse.ParseResult or str
         A url of file in http or https web address
     mode : str
-        mode of reading file, {"rb", "rt", "r"}
+        mode of reading file, 'rb', 'rt', 'r'
+
+    Raises
+    ------
+    If not http(s).
 
     Notes
     -----
-    If mode="b" or "rb" (binary read), the function returns file object to read
+    If mode='b' or 'rb' (binary read), the function returns file object to read
     else returns TextIOWrapper to read text with specified encoding in the URL
     """
-
+    mode = mode or "r"
     url_parsed = url if isinstance(url, ParseResult) else urlparse(url)
 
     if "r" not in mode:
-        raise ValueError("openning a url only allowed in read mode")
+        raise ValueError("opening a url only allowed in read mode")
 
     if url_parsed.scheme not in "https":
         raise ValueError("URL scheme must be http or https.")


Test patch:
diff --git a/tests/test_util/test_io.py b/tests/test_util/test_io.py
index 17eb1344e..31ceb11bc 100644
--- a/tests/test_util/test_io.py
+++ b/tests/test_util/test_io.py
@@ -1,24 +1,22 @@
 import bz2
 import gzip
-import os
 import pathlib
 import tempfile
 import zipfile
-import pytest
 
-from os import remove, rmdir
-from os.path import exists
-from tempfile import TemporaryDirectory
-from unittest import TestCase, main
+from itertools import product
+from urllib.parse import urlparse
+
+import pytest
 
 from cogent3.util.io import (
     _path_relative_to_zip_parent,
     atomic_write,
     get_format_suffixes,
     open_,
+    open_url,
     path_exists,
     remove_files,
-    open_url,
 )
 
 
@@ -31,316 +29,312 @@ __maintainer__ = "Gavin Huttley"
 __email__ = "Gavin.Huttley@anu.edu.au"
 __status__ = "Production"
 
+DATADIR = pathlib.Path(__file__).parent.parent / "data"
+
+
+@pytest.fixture
+def tmp_dir(tmpdir_factory):
+    return pathlib.Path(tmpdir_factory.mktemp("test_io"))
+
+
+def test_does_not_write_if_exception(tmp_dir):
+    """file does not exist if an exception raised before closing"""
+    test_filepath = tmp_dir / "Atomic_write_test"
+    with pytest.raises(AssertionError):
+        with atomic_write(test_filepath, mode="w") as f:
+            f.write("abc")
+            raise AssertionError
+    assert not test_filepath.exists()
+
+
+def test_writes_compressed_formats(tmp_dir):
+    """correctly writes / reads different compression formats"""
+    fpath = DATADIR / "sample.tsv"
+    expect = pathlib.Path(fpath).read_text()
+    for suffix in ["gz", "bz2", "zip"]:
+        outpath = tmp_dir / f"{fpath.name}.{suffix}"
+        with atomic_write(outpath, mode="wt") as f:
+            f.write(expect)
+
+        with open_(outpath) as infile:
+            got = infile.read()
+
+        assert got == expect, f"write failed for {suffix}"
+
+
+def test_rename(tmp_dir):
+    """Renames file as expected"""
+    test_filepath = tmp_dir / "Atomic_write_test"
+    # touch the filepath so it exists
+    f = open(test_filepath, "w").close()
+    assert test_filepath.exists()
+    # file should overwrite file if file already exists
+    with atomic_write(test_filepath, mode="w") as f:
+        f.write("abc")
+
+
+def test_atomic_write_noncontext(tmp_dir):
+    """atomic write works as more regular file object"""
+    path = tmp_dir / "foo.txt"
+    zip_path = path.parent / f"{path.name}.zip"
+    aw = atomic_write(path, in_zip=zip_path, mode="w")
+    aw.write("some data")
+    aw.close()
+    with open_(zip_path) as ifile:
+        got = ifile.read()
+    assert got == "some data"
+
+
+def test_open_handles_bom(tmp_dir):
+    """handle files with a byte order mark"""
+    text = "some text"
+
+    # plain text
+    textfile = tmp_dir / "sample.txt"
+    textfile.write_text(text, encoding="utf-8-sig")
+
+    # gzipped
+    gzip_file = tmp_dir / "sample.txt.gz"
+    with gzip.open(gzip_file, "wt", encoding="utf-8-sig") as outfile:
+        outfile.write(text)
+
+    # bzipped
+    bzip_file = tmp_dir / "sample.txt.bz2"
+    with bz2.open(bzip_file, "wt", encoding="utf-8-sig") as outfile:
+        outfile.write(text)
+
+    # zipped
+    zip_file = tmp_dir / "sample.zip"
+    with zipfile.ZipFile(zip_file, "w") as outfile:
+        outfile.write(textfile, "sample.txt")
+
+    for path in (bzip_file, gzip_file, textfile, zip_file):
+        with open_(path) as infile:
+            got = infile.read()
+            assert got == text, f"failed reading {path}"
+
+
+def test_aw_zip_from_path(tmp_dir):
+    """supports inferring zip archive name from path"""
+    path = tmp_dir / "foo.txt"
+    zip_path = path.parent / f"{path.name}.zip"
+    aw = atomic_write(zip_path, in_zip=True, mode="w")
+    aw.write("some data")
+    aw.close()
+    with open_(zip_path) as ifile:
+        got = ifile.read()
+        assert got == "some data"
+
+    path = tmp_dir / "foo2.txt"
+    zip_path = path.parent / f"{path.name}.zip"
+    aw = atomic_write(path, in_zip=zip_path, mode="w")
+    aw.write("some data")
+    aw.close()
+    with open_(zip_path) as ifile:
+        got = ifile.read()
+        assert got == "some data"
+
+
+def test_expanduser(tmp_dir):
+    """expands user correctly"""
+    # create temp file directory
+    home = pathlib.Path("~").expanduser()
+    test_filepath = tmp_dir / "Atomic_write_test"
+    test_filepath = str(test_filepath).replace(str(home), "~")
+    with atomic_write(test_filepath, mode="w") as f:
+        f.write("abc")
+
+
+def test_path_relative_to_zip_parent():
+    """correctly generates member paths for a zip archive"""
+    zip_path = pathlib.Path("some/path/to/a/data.zip")
+    for member in ("data/member.txt", "member.txt", "a/b/c/member.txt"):
+        got = _path_relative_to_zip_parent(zip_path, pathlib.Path(member))
+        assert got.parts[0] == "data"
+
+
+def test_remove_files():
+    """Remove files functions as expected"""
+    import os
+
+    # create list of temp file paths
+    test_filepaths = [
+        tempfile.NamedTemporaryFile(prefix="remove_files_test").name for i in range(5)
+    ]
+
+    # try to remove them with remove_files and verify that an IOError is
+    # raises
+    pytest.raises(OSError, remove_files, test_filepaths)
+    # now get no error when error_on_missing=False
+    remove_files(test_filepaths, error_on_missing=False)
+
+    # touch one of the filepaths so it exists
+    open(test_filepaths[2], "w").close()
+    # check that an error is raised on trying to remove the files...
+    pytest.raises(OSError, remove_files, test_filepaths)
+    # ... but that the existing file was still removed
+    assert not os.path.exists(test_filepaths[2])
+
+    # touch one of the filepaths so it exists
+    open(test_filepaths[2], "w").close()
+    # no error is raised on trying to remove the files
+    # (although 4 don't exist)...
+    remove_files(test_filepaths, error_on_missing=False)
+    # ... and the existing file was removed
+    assert not os.path.exists(test_filepaths[2])
+
+
+@pytest.mark.parametrize(
+    "name,expect",
+    (
+        ("suffixes.GZ", (None, "gz")),
+        ("suffixes.ABCD", ("abcd", None)),
+        ("suffixes.ABCD.BZ2", ("abcd", "bz2")),
+        ("suffixes.abcd.BZ2", ("abcd", "bz2")),
+        ("suffixes.ABCD.bz2", ("abcd", "bz2")),
+    ),
+)
+def test_get_format_suffixes_returns_lower_case(name, expect):
+    """should always return lower case"""
+    suffixes = get_format_suffixes(name)
+    assert suffixes == expect
+
+
+@pytest.mark.parametrize(
+    "name,expect",
+    (
+        ("no_suffixes", (None, None)),
+        ("suffixes.gz", (None, "gz")),
+        ("suffixes.abcd", ("abcd", None)),
+        ("suffixes.abcd.bz2", ("abcd", "bz2")),
+        ("suffixes.zip", (None, "zip")),
+    ),
+)
+def test_get_format_suffixes(name, expect):
+    """correctly return suffixes for compressed etc.. formats"""
+    suffixes = get_format_suffixes(name)
+    assert suffixes == expect
+
+
+@pytest.mark.parametrize(
+    "name,expect",
+    (
+        ("no_suffixes", (None, None)),
+        ("suffixes.gz", (None, "gz")),
+        ("suffixes.abcd", ("abcd", None)),
+        ("suffixes.abcd.bz2", ("abcd", "bz2")),
+        ("suffixes.zip", (None, "zip")),
+    ),
+)
+def test_get_format_suffixes_pathlib(name, expect):
+    """correctly return suffixes for compressed etc.. formats from pathlib"""
+    suffixes = get_format_suffixes(pathlib.Path(name))
+    assert suffixes == expect
+
+
+@pytest.mark.parametrize(
+    "val,expect",
+    (
+        ({}, False),
+        ("not an existing path", False),
+        ("(a,b,(c,d))", False),
+        ("(a:0.1,b:0.1,(c:0.1,d:0.1):0.1)", False),
+        (__file__, True),
+        (pathlib.Path(__file__), True),
+    ),
+)
+def test_path_exists(val, expect):
+    """robustly identifies whether an object is a valid path and exists"""
+    assert path_exists(val) == expect
+
+
+def test_open_reads_zip(tmp_dir):
+    """correctly reads a zip compressed file"""
+    text_path = tmp_dir / "foo.txt"
+    with open(text_path, "w") as f:
+        f.write("any str")
+
+    zip_path = tmp_dir / "foo.zip"
+    with zipfile.ZipFile(zip_path, "w") as zip:
+        zip.write(text_path)
+
+    with open_(zip_path) as got:
+        assert got.readline() == "any str"
+
+
+def test_open_writes_zip(tmp_dir):
+    """correctly writes a zip compressed file"""
+    zip_path = tmp_dir / "foo.txt.zip"
+
+    with open_(zip_path, "w") as f:
+        f.write("any str")
+
+    with zipfile.ZipFile(zip_path, "r") as zip:
+        name = zip.namelist()[0]
+        got = zip.open(name).read()
+        assert got == b"any str"
+
+
+def test_open_zip_multi(tmp_dir):
+    """zip with multiple records cannot be opened using open_"""
+    text_path1 = tmp_dir / "foo.txt"
+    with open(text_path1, "w") as f:
+        f.write("any str")
+
+    text_path2 = tmp_dir / "bar.txt"
+    with open(text_path2, "w") as f:
+        f.write("any str")
+
+    zip_path = tmp_dir / "foo.zip"
+    with zipfile.ZipFile(zip_path, "w") as zip:
+        zip.write(text_path1)
+        zip.write(text_path2)
+
+    with pytest.raises(ValueError):
+        open_(zip_path)
+
+
+@pytest.mark.parametrize(
+    "file_name,mode",
+    list(
+        product(
+            ("c_elegans_WS199_dna_shortened.fasta", "gff2_test.gff"),
+            ("r", "rb", "rt", None),
+        )
+    ),
+)
+def test_open_url(file_name, mode):
+    # None value for open_url mode defaults to "rb"
+    local_root = pathlib.Path("data")
+    remote_root = (
+        "https://raw.githubusercontent.com/cogent3/cogent3/develop/tests/data/{}"
+    )
+
+    with open_(local_root / file_name, mode=mode) as infile:
+        local_data = infile.read()
+
+    with open_url(remote_root.format(file_name), mode=mode) as infile:
+        remote_data = infile.read()
+    assert remote_data.splitlines() == local_data.splitlines()
+
+    # Test using a ParseResult for url
+    with open_url(urlparse(remote_root.format(file_name)), mode=mode) as infile:
+        remote_data = infile.read()
+    assert remote_data.splitlines() == local_data.splitlines()
+
+
+def test_open_url_write_exceptions():
+    """Test 'w' mode (should raise Exception)"""
+    with pytest.raises(Exception):
+        _ = open_url(
+            "https://raw.githubusercontent.com/cogent3/cogent3/develop/tests/data/gff2_test.gff",
+            mode="w",
+        )
+
 
-class AtomicWriteTests(TestCase):
-    """testing the atomic_write class."""
-
-    def test_does_not_write_if_exception(self):
-        """file does not exist if an exception raised before closing"""
-        # create temp file directory
-        with tempfile.TemporaryDirectory(".") as dirname:
-            dirname = pathlib.Path(dirname)
-            test_filepath = dirname / "Atomic_write_test"
-            with self.assertRaises(AssertionError):
-                with atomic_write(test_filepath, mode="w") as f:
-                    f.write("abc")
-                    raise AssertionError
-            self.assertFalse(test_filepath.exists())
-
-    def test_writes_compressed_formats(self):
-        """correctly writes / reads different compression formats"""
-        fpath = pathlib.Path("data/sample.tsv")
-        with open(fpath) as infile:
-            expect = infile.read()
-
-        with tempfile.TemporaryDirectory(".") as dirname:
-            dirname = pathlib.Path(dirname)
-            for suffix in ["gz", "bz2", "zip"]:
-                outpath = dirname / f"{fpath.name}.{suffix}"
-                with atomic_write(outpath, mode="wt") as f:
-                    f.write(expect)
-
-                with open_(outpath) as infile:
-                    got = infile.read()
-
-                self.assertEqual(got, expect, msg=f"write failed for {suffix}")
-
-    def test_rename(self):
-        """Renames file as expected"""
-        # create temp file directory
-        with tempfile.TemporaryDirectory(".") as dirname:
-            # create temp filepath
-            dirname = pathlib.Path(dirname)
-            test_filepath = dirname / "Atomic_write_test"
-            # touch the filepath so it exists
-            f = open(test_filepath, "w").close()
-            self.assertTrue(exists(test_filepath))
-            # file should overwrite file if file already exists
-            with atomic_write(test_filepath, mode="w") as f:
-                f.write("abc")
-
-    def test_atomic_write_noncontext(self):
-        """atomic write works as more regular file object"""
-        with TemporaryDirectory(dir=".") as dirname:
-            path = pathlib.Path(dirname) / "foo.txt"
-            zip_path = path.parent / f"{path.name}.zip"
-            aw = atomic_write(path, in_zip=zip_path, mode="w")
-            aw.write("some data")
-            aw.close()
-            with open_(zip_path) as ifile:
-                got = ifile.read()
-            self.assertEqual(got, "some data")
-
-    def test_open_handles_bom(self):
-        """handle files with a byte order mark"""
-        with TemporaryDirectory(dir=".") as dirname:
-            # create the different file types
-            dirname = pathlib.Path(dirname)
-
-            text = "some text"
-
-            # plain text
-            textfile = dirname / "sample.txt"
-            textfile.write_text(text, encoding="utf-8-sig")
-
-            # gzipped
-            gzip_file = dirname / "sample.txt.gz"
-            with gzip.open(gzip_file, "wt", encoding="utf-8-sig") as outfile:
-                outfile.write(text)
-
-            # bzipped
-            bzip_file = dirname / "sample.txt.bz2"
-            with bz2.open(bzip_file, "wt", encoding="utf-8-sig") as outfile:
-                outfile.write(text)
-
-            # zipped
-            zip_file = dirname / "sample.zip"
-            with zipfile.ZipFile(zip_file, "w") as outfile:
-                outfile.write(textfile, "sample.txt")
-
-            for path in (bzip_file, gzip_file, textfile, zip_file):
-                with open_(path) as infile:
-                    got = infile.read()
-                    self.assertEqual(got, text, msg=f"failed reading {path}")
-
-    def test_aw_zip_from_path(self):
-        """supports inferring zip archive name from path"""
-        with TemporaryDirectory(dir=".") as dirname:
-            path = pathlib.Path(dirname) / "foo.txt"
-            zip_path = path.parent / f"{path.name}.zip"
-            aw = atomic_write(zip_path, in_zip=True, mode="w")
-            aw.write("some data")
-            aw.close()
-            with open_(zip_path) as ifile:
-                got = ifile.read()
-                self.assertEqual(got, "some data")
-
-            path = pathlib.Path(dirname) / "foo2.txt"
-            zip_path = path.parent / f"{path.name}.zip"
-            aw = atomic_write(path, in_zip=zip_path, mode="w")
-            aw.write("some data")
-            aw.close()
-            with open_(zip_path) as ifile:
-                got = ifile.read()
-                self.assertEqual(got, "some data")
-
-    def test_expanduser(self):
-        """expands user correctly"""
-        # create temp file directory
-        home = pathlib.Path("~").expanduser()
-        with tempfile.TemporaryDirectory(dir=home) as dirname:
-            # create temp filepath
-            dirname = pathlib.Path(dirname)
-            test_filepath = dirname / "Atomic_write_test"
-            test_filepath = str(test_filepath).replace(str(home), "~")
-            with atomic_write(test_filepath, mode="w") as f:
-                f.write("abc")
-
-    def test_path_relative_to_zip_parent(self):
-        """correctly generates member paths for a zip archive"""
-        zip_path = pathlib.Path("some/path/to/a/data.zip")
-        for member in ("data/member.txt", "member.txt", "a/b/c/member.txt"):
-            got = _path_relative_to_zip_parent(zip_path, pathlib.Path(member))
-            self.assertEqual(got.parts[0], "data")
-
-
-class UtilsTests(TestCase):
-    """Tests of individual functions in utils"""
-
-    def setUp(self):
-        """ """
-        self.files_to_remove = []
-        self.dirs_to_remove = []
-
-    def tearDown(self):
-        """ """
-        list(map(remove, self.files_to_remove))
-        list(map(rmdir, self.dirs_to_remove))
-
-    def test_remove_files(self):
-        """Remove files functions as expected"""
-        # create list of temp file paths
-        test_filepaths = [
-            tempfile.NamedTemporaryFile(prefix="remove_files_test").name
-            for i in range(5)
-        ]
-
-        # try to remove them with remove_files and verify that an IOError is
-        # raises
-        self.assertRaises(OSError, remove_files, test_filepaths)
-        # now get no error when error_on_missing=False
-        remove_files(test_filepaths, error_on_missing=False)
-
-        # touch one of the filepaths so it exists
-        open(test_filepaths[2], "w").close()
-        # check that an error is raised on trying to remove the files...
-        self.assertRaises(OSError, remove_files, test_filepaths)
-        # ... but that the existing file was still removed
-        self.assertFalse(exists(test_filepaths[2]))
-
-        # touch one of the filepaths so it exists
-        open(test_filepaths[2], "w").close()
-        # no error is raised on trying to remove the files
-        # (although 4 don't exist)...
-        remove_files(test_filepaths, error_on_missing=False)
-        # ... and the existing file was removed
-        self.assertFalse(exists(test_filepaths[2]))
-
-    def test_get_format_suffixes_returns_lower_case(self):
-        """should always return lower case"""
-        a, b = get_format_suffixes("suffixes.GZ")
-        self.assertTrue(a == None and b == "gz")
-        a, b = get_format_suffixes("suffixes.ABCD")
-        self.assertTrue(a == "abcd" and b == None)
-        a, b = get_format_suffixes("suffixes.ABCD.BZ2")
-        self.assertTrue(a == "abcd" and b == "bz2")
-        a, b = get_format_suffixes("suffixes.abcd.BZ2")
-        self.assertTrue(a == "abcd" and b == "bz2")
-        a, b = get_format_suffixes("suffixes.ABCD.bz2")
-        self.assertTrue(a == "abcd" and b == "bz2")
-
-    def test_get_format_suffixes(self):
-        """correctly return suffixes for compressed etc.. formats"""
-        a, b = get_format_suffixes("no_suffixes")
-        self.assertTrue(a == b == None)
-        a, b = get_format_suffixes("suffixes.gz")
-        self.assertTrue(a == None and b == "gz")
-        a, b = get_format_suffixes("suffixes.abcd")
-        self.assertTrue(a == "abcd" and b == None)
-        a, b = get_format_suffixes("suffixes.abcd.bz2")
-        self.assertTrue(a == "abcd" and b == "bz2")
-        a, b = get_format_suffixes("suffixes.zip")
-        self.assertTrue(a == None and b == "zip")
-
-    def test_get_format_suffixes_pathlib(self):
-        """correctly return suffixes for compressed etc.. formats from pathlib"""
-        Path = pathlib.Path
-        a, b = get_format_suffixes(Path("no_suffixes"))
-        self.assertTrue(a == b == None)
-        a, b = get_format_suffixes(Path("suffixes.gz"))
-        self.assertTrue(a == None and b == "gz")
-        a, b = get_format_suffixes(Path("suffixes.abcd"))
-        self.assertTrue(a == "abcd" and b == None)
-        a, b = get_format_suffixes(Path("suffixes.abcd.bz2"))
-        self.assertTrue(a == "abcd" and b == "bz2")
-        a, b = get_format_suffixes(Path("suffixes.zip"))
-        self.assertTrue(a == None and b == "zip")
-
-    def test_path_exists(self):
-        """robustly identifies whether an object is a valid path and exists"""
-        self.assertFalse(path_exists({}))
-        self.assertFalse(path_exists("not an existing path"))
-        self.assertFalse(path_exists("(a,b,(c,d))"))
-        self.assertFalse(path_exists("(a:0.1,b:0.1,(c:0.1,d:0.1):0.1)"))
-        # works for a Path instance
-        p = pathlib.Path(__file__)
-        self.assertTrue(path_exists(p))
-        # or string instance
-        self.assertTrue(path_exists(__file__))
-
-    def test_open_reads_zip(self):
-        """correctly reads a zip compressed file"""
-        with TemporaryDirectory(dir=".") as dirname:
-            text_path = os.path.join(dirname, "foo.txt")
-            with open(text_path, "w") as f:
-                f.write("any str")
-
-            zip_path = os.path.join(dirname, "foo.zip")
-            with zipfile.ZipFile(zip_path, "w") as zip:
-                zip.write(text_path)
-
-            with open_(zip_path) as got:
-                self.assertEqual(got.readline(), "any str")
-
-    def test_open_writes_zip(self):
-        """correctly writes a zip compressed file"""
-        with TemporaryDirectory(dir=".") as dirname:
-            zip_path = pathlib.Path(dirname) / "foo.txt.zip"
-
-            with open_(zip_path, "w") as f:
-                f.write("any str")
-
-            with zipfile.ZipFile(zip_path, "r") as zip:
-                name = zip.namelist()[0]
-                got = zip.open(name).read()
-                self.assertEqual(got, b"any str")
-
-    def test_open_zip_multi(self):
-        """zip with multiple records cannot be opened using open_"""
-        with TemporaryDirectory(dir=".") as dirname:
-            text_path1 = os.path.join(dirname, "foo.txt")
-            with open(text_path1, "w") as f:
-                f.write("any str")
-
-            text_path2 = os.path.join(dirname, "bar.txt")
-            with open(text_path2, "w") as f:
-                f.write("any str")
-
-            zip_path = os.path.join(dirname, "foo.zip")
-            with zipfile.ZipFile(zip_path, "w") as zip:
-                zip.write(text_path1)
-                zip.write(text_path2)
-
-            with self.assertRaises(ValueError):
-                open_(zip_path)
-
-    def test_open_url(self):
-        from urllib.parse import urlparse
-
-        local_root = pathlib.Path("data")
-        remote_root = (
-            "https://raw.githubusercontent.com/cogent3/cogent3/develop/tests/data/{}"
+def test_open_url_exceptions():
+    """non-http(s) address for url (should raise Exception)"""
+    with pytest.raises(Exception):
+        _ = open_url(
+            "ftp://raw.githubusercontent.com/cogent3/cogent3/develop/tests/data/gff2_test.gff",
         )
-        for file_name in ("c_elegans_WS199_dna_shortened.fasta", "gff2_test.gff"):
-            for mode in ("r", "rb", "rt"):
-                with open_(local_root / file_name, mode=mode) as infile:
-                    local_data = infile.read()
-                with open_url(remote_root.format(file_name), mode=mode) as infile:
-                    remote_data = infile.read()
-                self.assertEqual(remote_data.splitlines(), local_data.splitlines())
-
-                # Test ParseResult for url
-                with open_url(
-                    urlparse(remote_root.format(file_name)), mode=mode
-                ) as infile:
-                    remote_data = infile.read()
-                self.assertEqual(remote_data.splitlines(), local_data.splitlines())
-
-                if "b" in mode:  # Test no value for mode, use default "rb" mode
-                    with open_url(remote_root.format(file_name)) as infile:
-                        remote_data = infile.read()
-                    self.assertEqual(remote_data.splitlines(), local_data.splitlines())
-
-        # Test "w" mode (should raise Exception)
-        url_data = "https://raw.githubusercontent.com/cogent3/cogent3/develop/tests/data/gff2_test.gff"
-        with pytest.raises(Exception):
-            file_url = open_url(url_data, mode="w")
-
-        # Test  non-http(s) address for url (should raise Exception)
-        url_data = "ftp://raw.githubusercontent.com/cogent3/cogent3/develop/tests/data/gff2_test.gff"
-        with pytest.raises(Exception):
-            file_url = open_url(url_data, mode="r")
-
-
-if __name__ == "__main__":
-    main()