def test_file_save_with_path(tmpdir): """ Saving a pathname should create intermediate directories as necessary. """ storage = FileSystemStorage(location=str(tmpdir)) assert not storage.exists("path/to") storage.save("path/to/test.file", io.StringIO("file saved with path")) assert storage.exists("path/to") assert storage.open("path/to/test.file").read() == "file saved with path" assert os.path.exists(os.path.join(str(tmpdir), "path", "to", "test.file"))
def test_listdir(tmpdir): """ File storage returns a tuple containing directories and files. """ storage = FileSystemStorage(location=str(tmpdir)) assert not storage.exists("storage_test_1") assert not storage.exists("storage_test_2") assert not storage.exists("storage_dir_1") storage.save("storage_test_1", io.StringIO("custom content")) storage.save("storage_test_2", io.StringIO("custom content")) os.mkdir(os.path.join(str(tmpdir), 'storage_dir_1')) dirs, files = storage.listdir("") assert set(dirs) == set(["storage_dir_1"]) assert set(files) == set(["storage_test_1", "storage_test_2"])
def test_file_path(tmpdir): """ File storage returns the full path of a file """ storage = FileSystemStorage(location=str(tmpdir)) assert not storage.exists("test.file") f = io.StringIO("custom contents") f_name = storage.save("test.file", f) assert storage.path(f_name) == os.path.join(str(tmpdir), f_name)
def test_makedirs_race_handling(tmpdir, monkeypatch): """ File storage should be robust against directory creation race conditions. """ real_makedirs = os.makedirs # Monkey-patch os.makedirs, to simulate a normal call, a raced call, # and an error. def fake_makedirs(path): if path == os.path.join(str(tmpdir), "normal"): real_makedirs(path) elif path == os.path.join(str(tmpdir), "raced"): real_makedirs(path) raise OSError(errno.EEXIST, "simulated EEXIST") elif path == os.path.join(str(tmpdir), "error"): raise OSError(errno.EACCES, "simulated EACCES") else: pytest.fail("unexpected argument %r" % path) monkeypatch.setattr(os, "makedirs", fake_makedirs) storage = FileSystemStorage(location=str(tmpdir)) storage.save("normal/test.file", io.StringIO("saved normally")) assert storage.open("normal/test.file").read() == "saved normally" storage.save("raced/test.file", io.StringIO("saved with race")) assert storage.open("raced/test.file").read() == "saved with race" # Check that OSErrors aside from EEXIST are still raised. with pytest.raises(OSError): storage.save("error/test.file", io.StringIO("not saved"))
def test_file_modified_time(tmpdir): """ File storage returns a Datetime object for the last modified time of a file. """ storage = FileSystemStorage(location=str(tmpdir)) assert not storage.exists("test.file") f = io.StringIO("custom contents") f_name = storage.save("test.file", f) mtime = storage.modified_time(f_name) assert mtime == datetime.datetime.fromtimestamp(os.path.getmtime(storage.path(f_name))) assert datetime.datetime.now() - storage.modified_time(f_name) < datetime.timedelta(seconds=2)
def test_file_save_without_name(tmpdir): """ File storage extracts the filename from the content object if no name is given explicitly. """ storage = FileSystemStorage(location=str(tmpdir)) assert not storage.exists("test.file") class NamedStringIO(io.StringIO): name = "test.file" f = NamedStringIO("custom contents") storage_f_name = storage.save(None, f) assert storage_f_name == f.name assert os.path.exists(os.path.join(str(tmpdir), f.name))
def test_remove_race_handling(tmpdir, monkeypatch): """ File storage should be robust against file removal race conditions. """ real_remove = os.remove # Monkey-patch os.remove, to simulate a normal call, a raced call, # and an error. def fake_remove(path): if path == os.path.join(str(tmpdir), "normal.file"): real_remove(path) elif path == os.path.join(str(tmpdir), "raced.file"): real_remove(path) raise OSError(errno.ENOENT, "simulated ENOENT") elif path == os.path.join(str(tmpdir), "error.file"): raise OSError(errno.EACCES, "simulated EACCES") else: pytest.fail("unexpected argument %r" % path) monkeypatch.setattr(os, "remove", fake_remove) storage = FileSystemStorage(location=str(tmpdir)) storage.save("normal.file", io.StringIO("delete normally")) storage.delete("normal.file") assert not storage.exists("normal.file") storage.save("raced.file", io.StringIO("delete with race")) storage.delete("raced.file") assert not storage.exists("normal.file") # Check that OSErrors aside from ENOENT are still raised. storage.save("error.file", io.StringIO("delete with error")) with pytest.raises(OSError): storage.delete("error.file")