File: C:/Users/fred/anaconda3/Lib/site-packages/astropy/io/fits/tests/conftest.py
# Licensed under a 3-clause BSD style license - see PYFITS.rst
import os
import pathlib
import shutil
import stat
import tempfile
import time
import pytest
from astropy.io import fits
@pytest.fixture(
params=[False, "str", "pathlib"], ids=["", "home_is_data", "home_is_data, pathlib"]
)
def home_is_data(request, monkeypatch):
"""
Pytest fixture to run a test case both with and without tilde paths.
In the tilde-path case, calls like self.data('filename.fits') will
produce '~/filename.fits', and environment variables will be temporarily
modified so that '~' resolves to the data directory.
"""
# This checks the value specified in the fixture annotation
if request.param:
# `request.instance` refers to the test case that's using this fixture.
request.instance.monkeypatch = monkeypatch
request.instance.set_home_as_data()
request.instance.set_paths_via_pathlib(request.param == "pathlib")
@pytest.fixture(
params=[False, "str", "pathlib"], ids=["", "home_is_data", "home_is_data, pathlib"]
)
def home_is_temp(request, monkeypatch):
"""
Pytest fixture to run a test case both with and without tilde paths.
In the tilde-path case, calls like self.temp('filename.fits') will
produce '~/filename.fits', and environment variables will be temporarily
modified so that '~' resolves to the temp directory. These files will also
be tracked so that, after the test case, we can verify no files were written
to a literal tilde path.
"""
# This checks the value specified in the fixture annotation
if request.param:
# `request.instance` refers to the test case that's using this fixture.
request.instance.monkeypatch = monkeypatch
request.instance.set_home_as_temp()
request.instance.set_paths_via_pathlib(request.param == "pathlib")
class FitsTestCase:
def setup_method(self):
self.data_dir = os.path.join(os.path.dirname(__file__), "data")
self.temp_dir = tempfile.mkdtemp(prefix="fits-test-")
self.home_is_data = False
self.home_is_temp = False
self.temp_files_used = set()
self.use_pathlib = False
# Restore global settings to defaults
# TODO: Replace this when there's a better way to in the config API to
# force config values to their defaults
fits.conf.enable_record_valued_keyword_cards = True
fits.conf.extension_name_case_sensitive = False
fits.conf.strip_header_whitespace = True
fits.conf.use_memmap = True
def teardown_method(self):
if self.home_is_temp:
# Verify that no files were written to a literal tilde path
for temp_file, temp_file_no_tilde in self.temp_files_used:
assert not os.path.exists(temp_file)
assert os.path.exists(temp_file_no_tilde)
if hasattr(self, "temp_dir") and os.path.exists(self.temp_dir):
tries = 3
while tries:
try:
shutil.rmtree(self.temp_dir)
break
except OSError:
# Probably couldn't delete the file because for whatever
# reason a handle to it is still open/hasn't been
# garbage-collected
time.sleep(0.5)
tries -= 1
fits.conf.reset("enable_record_valued_keyword_cards")
fits.conf.reset("extension_name_case_sensitive")
fits.conf.reset("strip_header_whitespace")
fits.conf.reset("use_memmap")
def copy_file(self, filename):
"""Copies a backup of a test data file to the temp dir and sets its
mode to writeable.
"""
shutil.copy(
os.path.expanduser(self.data(filename)),
os.path.expanduser(self.temp(filename)),
)
os.chmod(os.path.expanduser(self.temp(filename)), stat.S_IREAD | stat.S_IWRITE)
def data(self, filename):
"""Returns the path to a test data file."""
if self.home_is_data:
prefix = "~"
else:
prefix = self.data_dir
if self.use_pathlib:
return pathlib.Path(prefix, filename)
return os.path.join(prefix, filename)
def temp(self, filename):
"""Returns the full path to a file in the test temp dir."""
real_target = os.path.join(self.temp_dir, filename)
if self.home_is_temp:
prefix = "~"
# Record the '~' path and the intended path, for use
# in `home_is_temp`
self.temp_files_used.add((os.path.join(prefix, filename), real_target))
else:
prefix = self.temp_dir
if self.use_pathlib:
return pathlib.Path(prefix, filename)
return os.path.join(prefix, filename)
def set_home_as_data(self):
"""
This overrides the HOME environment variable, so that paths beginning
with '~/' expand to the data directory. Used by the `home_is_data`
fixture.
"""
self.home_is_data = True
# For Unix
self.monkeypatch.setenv("HOME", self.data_dir)
# For Windows
self.monkeypatch.setenv("USERPROFILE", self.data_dir)
def set_home_as_temp(self):
"""
This overrides the HOME environment variable, so that paths beginning
with '~/' expand to the temp directory. In conjunction with
self.temp(), temporary files are tracked as they are created, so we can
verify they end up in the temporary directory and not unexpected places
in the filesystem. Used by the `home_is_temp` fixture.
"""
self.home_is_temp = True
# For Unix
self.monkeypatch.setenv("HOME", self.temp_dir)
# For Windows
self.monkeypatch.setenv("USERPROFILE", self.temp_dir)
def set_paths_via_pathlib(self, use_pathlib):
self.use_pathlib = use_pathlib