1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
import contextlib
import os
import shutil
import sys
import warnings
from functools import wraps
from pathlib import Path
import pytest
import imageio as iio
IS_PYPY = "__pypy__" in sys.builtin_module_names
def pytest_configure(config):
config.addinivalue_line(
"markers",
"needs_internet: Marks a test that requires an active interent connection."
" (deselect with '-m \"not needs_internet\"').",
)
def pytest_addoption(parser):
parser.addoption(
"--test-images",
action="store",
metavar="GIT_REPO",
default="https://github.com/imageio/test_images.git",
help="Repository containing the test images "
" (default: %(default)s). Use `file:///path/to/test_images`"
" to clone from a local repository and save testing bandwidth.",
)
parser.addoption(
"--github-token",
action="store",
default=None,
help="If set, this value will be used as a token to authenticate with the GitHub API.",
)
parser.addoption(
"--github-username",
action="store",
default=None,
help="If set, this value will be used as the username to authenticate with the GitHub API.",
)
@contextlib.contextmanager
def working_directory(path):
"""
A context manager which changes the working directory to the given
path, and then changes it back to its previous value on exit.
Usage:
> # Do something in original directory
> with working_directory('/my/new/path'):
> # Do something in new directory
> # Back to old directory
Credit goes to @anjos .
"""
prev_cwd = os.getcwd()
os.chdir(path)
try:
yield
finally:
os.chdir(prev_cwd)
@pytest.fixture(scope="session")
def test_images(request, pytestconfig):
"""A collection of test images.
Note: The images are cached persistently (across test runs) in
the project's root folder (at `project_root/.test_images`).
"""
# A temporary directory loaded with the test image files
# downloaded once in the beginning
checkout_dir = request.config.cache.get("imageio_test_binaries", None)
use_internet = "not needs_internet" not in pytestconfig.getoption("-m")
if checkout_dir is not None and not Path(checkout_dir).exists():
# cache value set, but cache is gone :( ... recreate
checkout_dir = None
if checkout_dir is None:
# download test images and other binaries
checkout_dir = Path(__file__).parents[1] / ".test_images"
if not checkout_dir.exists() and not use_internet:
pytest.skip("Internet use disabled and `.test_images` not found.")
try:
checkout_dir.mkdir()
except FileExistsError:
pass # dir exist, validate and fail later
else:
with working_directory(checkout_dir):
repo_location = request.config.getoption("--test-images")
os.system(f"git clone {repo_location} .")
request.config.cache.set("imageio_test_binaries", str(checkout_dir))
checkout_dir = Path(checkout_dir)
if use_internet:
with working_directory(checkout_dir):
result = os.system("git pull")
if result != 0:
request.config.cache.set("imageio_test_binaries", None)
raise RuntimeError(
"Cache directory is corrupt. Delete `.test_images` at project root."
)
return checkout_dir
@pytest.fixture()
def image_files(test_images, tmp_path):
"""A copy of the test images
This is intended for tests that write to or modify the test images.
"""
for item in test_images.iterdir():
if item.is_file():
shutil.copy(item, tmp_path / item.name)
yield tmp_path
@pytest.fixture()
def clear_plugins():
old_extensions = iio.config.known_extensions.copy()
old_plugins = iio.config.known_plugins.copy()
iio.config.known_extensions.clear()
iio.config.known_plugins.clear()
yield
iio.config.known_extensions.clear()
iio.config.known_plugins.clear()
iio.config.known_plugins.update(old_plugins)
iio.config.known_extensions.update(old_extensions)
@pytest.fixture()
def invalid_file(tmp_path, request):
ext = request.param
with open(tmp_path / ("foo" + ext), "w") as file:
file.write("This is not an image.")
return tmp_path / ("foo" + ext)
@pytest.fixture()
def tmp_userdir(tmp_path):
ud = tmp_path / "userdir"
ud.mkdir(exist_ok=True)
if sys.platform.startswith("win"):
user_dir_env = "LOCALAPPDATA"
else:
user_dir_env = "IMAGEIO_USERDIR"
old_user_dir = os.getenv(user_dir_env, None)
os.environ[user_dir_env] = str(ud)
yield ud
if old_user_dir is not None:
os.environ[user_dir_env] = old_user_dir
else:
del os.environ[user_dir_env]
def deprecated_test(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
with warnings.catch_warnings(record=True):
return fn(*args, **kwargs)
return wrapper
|