def test_remove_raises_oserror(self, tmp_path, monkeypatch, capsys): def mock_remove(p): raise OSError("MOCK_REMOVE: %s" % p) setup_workdir(tmp_path, [ "foo/one.xxx", "more/two.xxx", ]) problematic_file1 = tmp_path / "foo/one.xxx" problematic_file1 = problematic_file1.relative_to(tmp_path) problematic_file2 = tmp_path / "more/two.xxx" problematic_file2 = problematic_file2.relative_to(tmp_path) with cd(str(tmp_path)): monkeypatch.setattr("path.Path.remove_p", mock_remove) cleanup_files(["**/*.xxx"]) captured = capsys.readouterr() print(captured.out) expected1 = "REMOVE: %s" % problematic_file1 expected2 = "OSError: MOCK_REMOVE: %s" % problematic_file1 assert expected1 in captured.out assert expected2 in captured.out expected2 = "OSError: MOCK_REMOVE: %s" % problematic_file2 assert expected2 in captured.out
def test_within_readonly_dir__is_not_removed(self, tmp_path, capsys): # -- SETUP: readonly_mode = 0o555 # dr-xr-xr-x (disabled: write-mode) setup_workdir(tmp_path, ["one.xxx/.ignored", "readonly.dir/two.xxx/.ignored"]) my_dir1 = tmp_path / "one.xxx/" readonly_dir = tmp_path / "readonly.dir/" my_dir2 = readonly_dir / "two.xxx/" assert my_dir1.exists() and my_dir1.is_dir() assert my_dir2.exists() and my_dir2.is_dir() readonly_dir_initial_mode = stat.S_IMODE(readonly_dir.stat().st_mode) readonly_dir.chmod(readonly_mode) readonly_dir_mode = stat.S_IMODE(readonly_dir.stat().st_mode) print("DIAG: readonly_dir.mode= 0o%o" % readonly_dir_mode) assert path_is_readonly(readonly_dir) # -- EXECUTE AND VERIFY: cwd = tmp_path cleanup_dirs(["**/*.xxx"], cwd) captured = capsys.readouterr() assert not my_dir1.exists(), "OOPS: my_dir1 was NOT_REMOVED" assert my_dir2.exists(), "OOPS: my_dir2 was REMOVED" expected = "RMTREE: {0}".format(my_dir2) assert expected in captured.out # -- CLEANUP: readonly_dir.chmod(readonly_dir_initial_mode)
def test_cleanup_dirs_without_configfile(self, tmp_path): # -- SETUP: setup_workdir(tmp_path, [ ".venv_DEFAULT/.dir", "downloads/.dir", ]) my_dir1 = tmp_path / ".venv_DEFAULT" my_dir2 = tmp_path / "downloads" assert my_dir1.exists() and my_dir1.is_dir() assert my_dir2.exists() and my_dir2.is_dir() tasks_dir = tmp_path / "tasks.py" tasks_dir.write_text(TASKS_FILE_TEXT_USING_CLEANUP_MODULE_ONLY) config_dir = tmp_path / "invoke.yaml" assert not config_dir.exists() # -- EXECUTE AND VERIFY: with use_subprocess_coverage(tmp_path): with cd(str(tmp_path)): output = ensure_text(run_with_output("invoke cleanup.all")) assert not my_dir1.exists() assert not my_dir2.exists() expected1 = "RMTREE: .venv_DEFAULT" expected2 = "RMTREE: downloads" assert expected1 in output assert expected2 in output
def test_with_configfile_and_cleanup_files_overrides_default( self, tmp_path): # -- SETUP: setup_workdir(tmp_path, [ "one.xxx", "more/two.zzz", ]) my_file1 = tmp_path / "one.xxx" my_file2 = tmp_path / "more/two.zzz" assert my_file1.exists() and my_file1.is_file() assert my_file2.exists() and my_file2.is_file() tasks_file = tmp_path / "tasks.py" tasks_file.write_text(TASKS_FILE_TEXT_USING_CLEANUP_MODULE_ONLY) config_file = tmp_path / "invoke.yaml" config_file.write_text(u""" cleanup_all: files: - "**/*.xxx" - "**/*.zzz" """) # -- EXECUTE AND VERIFY: with use_subprocess_coverage(tmp_path): with cd(str(tmp_path)): output = ensure_text(run_with_output("invoke cleanup.all")) assert not my_file1.exists() assert not my_file2.exists() expected1 = "REMOVE: one.xxx" expected2 = "REMOVE: more/two.zzz" assert expected1 in output assert expected2 in output
def test_with_configfile_and_cleanup_extra_directories_extends_default( self, tmp_path): # -- SETUP: setup_workdir(tmp_path, [ "one.xxx/.dir", "more/two.zzz/.dir", ]) my_dir1 = tmp_path / "one.xxx" my_dir2 = tmp_path / "more/two.zzz" assert my_dir1.exists() and my_dir1.is_dir() assert my_dir2.exists() and my_dir2.is_dir() tasks_dir = tmp_path / "tasks.py" tasks_dir.write_text(TASKS_FILE_TEXT_USING_CLEANUP_MODULE_ONLY) config_dir = tmp_path / "invoke.yaml" config_dir.write_text(u""" cleanup: extra_directories: - "**/*.xxx" - "**/*.zzz" """) # -- EXECUTE AND VERIFY: output = run_with_output_in_directory(tmp_path) assert not my_dir1.exists() assert not my_dir2.exists() expected1 = "RMTREE: one.xxx" expected2 = "RMTREE: more/two.zzz" assert expected1 in output assert expected2 in output
def test_cleanup_files_without_configfile(self, tmp_path): # -- SETUP: setup_workdir(tmp_path, [ "DEFAULT_FILE.bak", "more/DEFAULT_FILE.log", ]) my_file1 = tmp_path / "DEFAULT_FILE.bak" my_file2 = tmp_path / "more/DEFAULT_FILE.log" assert my_file1.exists() and my_file1.is_file() assert my_file2.exists() and my_file2.is_file() tasks_file = tmp_path / "tasks.py" tasks_file.write_text(TASKS_FILE_TEXT_USING_CLEANUP_MODULE_ONLY) config_file = tmp_path / "invoke.yaml" assert not config_file.exists() # -- EXECUTE AND VERIFY: output = run_with_output_in_directory(tmp_path) assert not my_file1.exists() assert not my_file2.exists() expected1 = "REMOVE: DEFAULT_FILE.bak" expected2 = "REMOVE: more/DEFAULT_FILE.log" assert expected1 in output assert expected2 in output
def test_within_no_permissions_dir__is_not_removed(self, tmp_path, capsys): # -- SETUP: no_permission_mode = 0o000 # d---.---.--- (NO_PERMISSIONS) setup_workdir(tmp_path, ["one.xxx/.ignored", "no_permission/two.xxx/.ignored"]) my_dir1 = tmp_path / "one.xxx/" no_permission_dir = tmp_path / "no_permission/" my_dir2 = no_permission_dir / "two.xxx/" assert my_dir1.exists() and my_dir1.is_dir() assert my_dir2.exists() and my_dir2.is_dir() no_permission_initial_mode = stat.S_IMODE( no_permission_dir.stat().st_mode) no_permission_dir.chmod(no_permission_mode) no_permission_mode = stat.S_IMODE(no_permission_dir.stat().st_mode) print("DIAG: no_permission_dir.mode= 0o%o" % no_permission_mode) assert not path_is_readable(no_permission_dir) assert not path_is_writable(no_permission_dir) assert not path_is_executable(no_permission_dir) # -- EXECUTE AND CLEANUP: cwd = tmp_path cleanup_dirs(["**/*.xxx"], cwd) captured = capsys.readouterr() no_permission_dir.chmod(no_permission_initial_mode) # -- VERIFY: assert not my_dir1.exists(), "OOPS: my_dir1 was NOT_REMOVED" assert my_dir2.exists(), "OOPS: my_dir2 was REMOVED" expected = "RMTREE: {0}".format(my_dir2) assert expected not in captured.out, "OOPS: Traversal into NO_PERMISSION.dir"
def test_with_file_in_readonly_dir_is_not_removed(self, tmp_path, capsys): # -- SETUP: readonly_mode = 0o555 # dr-xr-xr-x (disabled: write-mode) setup_workdir(tmp_path, [ "readonly.dir/one.xxx", ]) my_dir = tmp_path/"readonly.dir" my_file1 = my_dir/"one.xxx" my_dir.chmod(readonly_mode) assert my_file1.exists() and my_file1.is_file() my_dir_mode = stat.S_IMODE(my_file1.stat().st_mode) print("DIAG: my_dir.mode= 0o%o" % my_dir_mode) assert path_is_readable(my_dir) assert not path_is_writable(my_dir) # -- EXECUTE AND VERIFY: Best-effort, ignore read-only file(s) # with pytest.raises(OSError, match="Permission denied"): cwd = tmp_path cleanup_files(["**/*.xxx"], cwd) captured = capsys.readouterr() assert my_file1.exists(), "OOPS: my_file1 was removed." if python_version < python35: # -- REASON: OSError is not raised for newer py3 versions. assert "OSError" in captured.out assert "Permission denied:" in captured.out assert str(my_file1) in captured.out
def test_invoke_removes_other_cleanup_dirs(self, tmp_path): # -- SETUP: setup_workdir(tmp_path, [ "one.xxx/.dir", "more/two.xxx/.dir", ]) my_dir1 = tmp_path / "one.xxx" my_dir2 = tmp_path / "more/two.xxx" assert my_dir1.exists() and my_dir1.is_dir() assert my_dir2.exists() and my_dir2.is_dir() tasks_file = tmp_path / "tasks.py" tasks_file.write_text(u""" from __future__ import absolute_import, print_function from invoke import task, Collection import invoke_cleanup as cleanup namespace = Collection() namespace.add_collection(Collection.from_module(cleanup), name="cleanup") namespace.configure(cleanup.namespace.configuration()) from invoke_cleanup import config_add_cleanup_dirs config_add_cleanup_dirs(["**/*.xxx", "one.xxx"]) """) # -- EXECUTE AND VERIFY: output = run_with_output_in_directory(tmp_path) assert not my_dir1.exists() assert not my_dir2.exists() expected1 = "RMTREE: one.xxx" expected2 = "RMTREE: more/two.xxx" assert expected1 in output assert expected2 in output
def test_with_two_patterns(self, tmp_path): # -- SETUP: setup_workdir(tmp_path, ["one.xxx/.ignored", "more/two.zzz/.ignored"]) my_dir1 = tmp_path / "one.xxx" my_dir2 = tmp_path / "more/two.zzz" assert my_dir1.exists() and my_dir1.is_dir() assert my_dir2.exists() and my_dir2.is_dir() # -- EXECUTE AND VERIFY: cwd = tmp_path cleanup_dirs(["**/*.xxx/", "**/*.zzz/"], cwd) assert not my_dir1.exists(), "OOPS: my_dir1 was NOT_REMOVED" assert not my_dir2.exists(), "OOPS: my_dir2 was NOT_REMOVED"
def test_with_one_pattern_in_other_workdir_subtree(self, tmp_path): # -- SETUP: setup_workdir(tmp_path, ["one.xxx/.ignored", "other/two.xxx/.ignored"]) my_dir1 = tmp_path / "one.xxx" my_dir2 = tmp_path / "other/two.xxx" assert my_dir1.exists() and my_dir1.is_dir() assert my_dir2.exists() and my_dir2.is_dir() # -- EXECUTE AND VERIFY: cwd = tmp_path cleanup_dirs(["**/*.xxx"], workdir=cwd / "other") assert my_dir1.exists(), "OOPS: my_dir1 was REMOVED" assert not my_dir2.exists(), "OOPS: my_dir2 was NOT_REMOVED"
def test_with_exact_name(self, tmp_path): # -- SETUP: setup_workdir(tmp_path, ["one.xxx/.ignored", "more/two.xxx/.ignored"]) my_dir1 = tmp_path / "one.xxx" my_dir2 = tmp_path / "more/two.xxx" assert my_dir1.exists() and my_dir1.is_dir() assert my_dir2.exists() and my_dir2.is_dir() # -- EXECUTE AND VERIFY: cwd = tmp_path cleanup_dirs(["more/two.xxx"], cwd) assert my_dir1.exists(), "OOPS: my_dir1 was REMOVED" assert not my_dir2.exists(), "OOPS: my_dir2 was NOT REMOVED"
def test_without_any_matching_dirs(self, tmp_path): # -- SETUP: setup_workdir(tmp_path, ["one.xxx/.ignored", "more/two.xxx/.ignored"]) my_dir1 = tmp_path / "one.xxx" my_dir2 = tmp_path / "more/two.xxx" assert my_dir1.exists() and my_dir1.is_dir() assert my_dir2.exists() and my_dir2.is_dir() # -- EXECUTE AND VERIFY: cwd = tmp_path cleanup_dirs(["**/*.OTHER"], cwd) assert my_dir1.exists(), "OOPS: my_dir1 was REMOVED" assert my_dir2.exists(), "OOPS: my_dir2 was REMOVED"
def test_dry_run__should_removes_no_dirs(self, tmp_path): # -- SETUP: setup_workdir(tmp_path, ["one.xxx/.ignored", "more/two.xxx/.ignored"]) my_dir1 = tmp_path / "one.xxx" my_dir2 = tmp_path / "more/two.xxx" assert my_dir1.exists() and my_dir1.is_dir() assert my_dir2.exists() and my_dir2.is_dir() # -- EXECUTE AND VERIFY: cwd = tmp_path cleanup_dirs(["**/*.xxx"], cwd, dry_run=True) assert my_dir1.exists(), "OOPS: my_dir1 was REMOVED" assert my_dir2.exists(), "OOPS: my_dir2 was REMOVED"
def test_with_one_pattern_in_other_workdir_subtree(self, tmp_path): # -- SETUP: setup_workdir(tmp_path, [ "one.xxx", "other/more/two.xxx" ]) my_file1 = tmp_path/"one.xxx" my_file2 = tmp_path/"other/more/two.xxx" assert my_file1.exists() and my_file1.is_file() assert my_file2.exists() and my_file2.is_file() # -- EXECUTE AND VERIFY: cwd = tmp_path cleanup_files(["**/*.xxx"], cwd/"other") assert my_file1.exists() assert not my_file2.exists()
def test_with_two_patterns(self, tmp_path): # -- SETUP: setup_workdir(tmp_path, [ "one.xxx", "more/two.zzz" ]) my_file1 = tmp_path/"one.xxx" my_file2 = tmp_path/"more/two.zzz" assert my_file1.exists() and my_file1.is_file() assert my_file2.exists() and my_file2.is_file() # -- EXECUTE AND VERIFY: cwd = tmp_path cleanup_files(["**/*.xxx", "**/*.zzz"], cwd) assert not my_file1.exists(), "OOPS: my_file1 was NOT_REMOVED" assert not my_file2.exists(), "OOPS: my_file2 was NOT_REMOVED"
def test_removes_uncommitted_files(self, mode, tmp_path, capsys, monkeypatch): # -- SETUP: setup_workdir(tmp_path, [ "one.xxx", "two.xxx", ]) my_file1 = tmp_path / "one.xxx" my_file2 = tmp_path / "two.xxx" assert my_file1.exists() and my_file1.is_file() assert my_file2.exists() and my_file2.is_file() # -- EXECUTE AND VERIFY: Path = tmp_path.__class__ git_clean_dry_run = (mode == "dry_run") curdir = Path(".").resolve() with cd(str(tmp_path)): work_dir = Path(".").resolve() not_in_curdir = not tmp_path.samefile(curdir) print("WORK_DIR: %s (work_dir is not CURDIR: %s)" % (work_dir, not_in_curdir)) assert not_in_curdir, "DANGER_ZONE.SANITY_CHECK_BARRIER.saved_you" # with capsys.disabled(): run("git init") git_dir = tmp_path / ".git/" assert git_dir.is_dir() run('git add one.xxx') run('git commit -m"INITIAL" one.xxx') run("git status") config = Config(DEFAULT_CONFIG) ctx = Context(config=config) ctx.config.run.dry = False ctx.config.git_clean.interactive = False monkeypatch.setattr("_pytest.capture.DontReadFromInput.read", mock_read_from_stdin) git_clean(ctx, force=True, dry_run=git_clean_dry_run) assert my_file1.exists(), "OOPS: my_file1 was REMOVED" if git_clean_dry_run: # -- DRY-RUN MODE: captured = capsys.readouterr() assert "Would remove two.xxx" in captured.out assert my_file2.exists(), "OOPS: my_file2 was REMOVED" else: assert not my_file2.exists(), "OOPS: my_file2 was NOT_REMOVED"
def test_without_any_matching_files(self, tmp_path): # -- SETUP: setup_workdir(tmp_path, [ "one.xxx", "more/two.xxx" ]) my_file1 = tmp_path/"one.xxx" my_file2 = tmp_path/"more/two.xxx" assert my_file1.exists() and my_file1.is_file() assert my_file2.exists() and my_file2.is_file() # -- EXECUTE AND VERIFY: Best-effort, ignore read-only file(s) # with pytest.raises(OSError, match="Permission denied"): cwd = tmp_path cleanup_files(["**/*.zzz"], cwd) assert my_file1.exists(), "OOPS: my_file1 was REMOVED" assert my_file2.exists(), "OOPS: my_file2 was REMOVED"
def test_with_one_pattern_in_current_workdir(self, tmp_path): # -- SETUP: setup_workdir(tmp_path, [ "one.xxx/.ignored", "two.xxx/.ignored", "more/ignored.xxx/.ignored" ]) my_dir1 = tmp_path / "one.xxx" my_dir2 = tmp_path / "two.xxx" my_dir3 = tmp_path / "more/ignored.xxx" assert my_dir1.exists() and my_dir1.is_dir() assert my_dir2.exists() and my_dir2.is_dir() assert my_dir3.exists() and my_dir3.is_dir() # -- EXECUTE AND VERIFY: cwd = tmp_path cleanup_dirs(["*.xxx"], cwd) assert not my_dir1.exists(), "OOPS: my_dir1 was NOT_REMOVED" assert not my_dir2.exists(), "OOPS: my_dir2 was NOT_REMOVED" assert my_dir3.exists(), "OOPS: my_dir3 was REMOVED"
def test_with_exact_name(self, tmp_path): remove_pattern = "more/two.xxx" # -- SETUP: setup_workdir(tmp_path, [ "one.xxx", "more/two.xxx" ]) my_file1 = tmp_path/"one.xxx" my_file2 = tmp_path/"more/two.xxx" assert my_file1.exists() and my_file1.is_file() assert my_file2.exists() and my_file2.is_file() # -- EXECUTE AND VERIFY: Best-effort, ignore read-only file(s) # with pytest.raises(OSError, match="Permission denied"): cwd = tmp_path cleanup_files([remove_pattern], cwd) assert my_file1.exists(), "OOPS: my_file1 was REMOVED" assert not my_file2.exists(), "OOPS: my_file2 was NOT_REMOVED"
def test_without_workdir_param_uses_current_directory(self, tmp_path): # -- SETUP: setup_workdir(tmp_path, [ "one.xxx/.ignored", "two.xxx/.ignored", "more/ignored.xxx/.ignored" ]) my_dir1 = tmp_path / "one.xxx" my_dir2 = tmp_path / "two.xxx" my_dir3 = tmp_path / "more/ignored.xxx" assert my_dir1.exists() and my_dir1.is_dir() assert my_dir2.exists() and my_dir2.is_dir() assert my_dir3.exists() and my_dir3.is_dir() # -- EXECUTE AND VERIFY: cwd = tmp_path with cd(str(cwd)): # -- STRING-CONVERSION (needed for: python2.7) cleanup_dirs(["*.xxx"]) assert not my_dir1.exists(), "OOPS: my_dir1 was NOT_REMOVED" assert not my_dir2.exists(), "OOPS: my_dir2 was NOT_REMOVED" assert my_dir3.exists(), "OOPS: my_dir3 was REMOVED"
def test_with_matching_file__should_skip_remove_and_showit_in_verbose_mode( self, tmp_path, capsys): # -- SETUP: setup_workdir(tmp_path, ["one.xxx/.ignored", "more/two.xxx"]) my_dir1 = tmp_path / "one.xxx" my_file2 = tmp_path / "more/two.xxx" assert my_dir1.exists() and my_dir1.is_dir() assert my_file2.exists() and my_file2.is_file() # -- EXECUTE AND VERIFY: cwd = tmp_path cleanup_dirs(["**/*.xxx"], cwd, verbose=True) captured = capsys.readouterr() assert not my_dir1.exists(), "OOPS: my_dir1 was NOT_REMOVED" assert my_file2.exists(), "OOPS: my_file2 was REMOVED" # -- ONLY IN VERBOSE MODE: expected = "RMTREE: {0} (SKIPPED: Not a directory)".format(my_file2) assert expected in captured.out
def test_invoke_calls_other_task_that_uses_cleanup_dirs(self, tmp_path): # -- SETUP: setup_workdir(tmp_path, [ "one.xxx/.dir", "more/two.xxx/.dir", ]) my_dir1 = tmp_path / "one.xxx" my_dir2 = tmp_path / "more/two.xxx" assert my_dir1.exists() and my_dir1.is_dir() assert my_dir2.exists() and my_dir2.is_dir() tasks_file = tmp_path / "tasks.py" tasks_file.write_text(u""" from __future__ import absolute_import, print_function from invoke import task, Collection import invoke_cleanup as cleanup from invoke_cleanup import cleanup_dirs @task def foo_clean(ctx): print("CALLED: foo_clean") cleanup_dirs(["**/*.xxx"]) namespace = Collection(foo_clean) namespace.add_collection(Collection.from_module(cleanup), name="cleanup") namespace.configure(cleanup.namespace.configuration()) from invoke_cleanup import cleanup_all_tasks cleanup_all_tasks.add_task(foo_clean, name="foo_clean") cleanup_all_tasks.configure(namespace.configuration()) """) # -- EXECUTE AND VERIFY: with cd(str(tmp_path)): output = ensure_text(run_with_output("invoke cleanup.all")) assert not my_dir1.exists() assert not my_dir2.exists() expected1 = "RMTREE: one.xxx" expected2 = "RMTREE: more/two.xxx" assert expected1 in output assert expected2 in output
def test_with_matching_file__should_skip_remove(self, tmp_path, capsys): # -- SETUP: setup_workdir(tmp_path, ["one.xxx/.ignored", "more/two.xxx"]) my_dir1 = tmp_path / "one.xxx" my_file2 = tmp_path / "more/two.xxx" assert my_dir1.exists() and my_dir1.is_dir() assert my_file2.exists() and my_file2.is_file() # -- EXECUTE AND VERIFY: cwd = tmp_path cleanup_dirs(["**/*.xxx"], cwd) captured = capsys.readouterr() assert not my_dir1.exists(), "OOPS: my_dir1 was NOT_REMOVED" assert my_file2.exists(), "OOPS: my_file2 was REMOVED" # -- ONLY IN NON-VERBOSE MODE: expected1 = "RMTREE: {0}".format(my_file2) expected2 = "REMOVE: {0}".format(my_file2) assert expected1 not in captured.out assert expected2 not in captured.out
def test_skips_rmtree_below_sys_executable_basedir(self, tmp_path, monkeypatch, capsys): """SKIP-SUICIDE in context of cleanup_dirs in virtual environment.""" setup_workdir(tmp_path, [ "opt/python_x.y/bin/python", "opt/python_x.y/lib/foo/one.xxx/.dir" ]) python_basedir = tmp_path / "opt/python_x.y" mock_sys_executable = python_basedir / "bin/python" mock_sys_executable = str(mock_sys_executable.absolute()) problematic_dir = python_basedir / "lib/foo/one.xxx" problematic_dir = problematic_dir.relative_to(tmp_path) with cd(str(tmp_path)): monkeypatch.setattr("sys.executable", mock_sys_executable) cleanup_dirs(["**/*.xxx"], dry_run=True) captured = capsys.readouterr() print(captured.out) expected = "SKIP-SUICIDE: 'opt/python_x.y/lib/foo/one.xxx'" assert expected in captured.out
def test_with_configfile_and_cleanup_directories_overrides_default( self, tmp_path): # -- SETUP: setup_workdir( tmp_path, [ # -- HINT: DEFAULT cleanup.directories = [] EMPTY-LIST ".venv_DEFAULT/.dir", "one.xxx/.dir", "more/two.zzz/.dir", ]) my_dir0 = tmp_path / ".venv_DEFAULT" my_dir1 = tmp_path / "one.xxx" my_dir2 = tmp_path / "more/two.zzz" assert my_dir0.exists() and my_dir0.is_dir() assert my_dir1.exists() and my_dir1.is_dir() assert my_dir2.exists() and my_dir2.is_dir() tasks_dir = tmp_path / "tasks.py" tasks_dir.write_text(TASKS_FILE_TEXT_USING_CLEANUP_MODULE_ONLY) config_dir = tmp_path / "invoke.yaml" config_dir.write_text(u""" cleanup_all: directories: - "**/*.xxx" - "**/*.zzz" """) # -- EXECUTE AND VERIFY: with use_subprocess_coverage(tmp_path): with cd(str(tmp_path)): output = ensure_text(run_with_output("invoke cleanup.all")) assert my_dir0.exists( ), "OOPS: DEFAULT cleanup_all.directories was NOT_OVERWRITTEN" assert not my_dir1.exists() assert not my_dir2.exists() expected1 = "RMTREE: one.xxx" expected2 = "RMTREE: more/two.zzz" assert expected1 in output assert expected2 in output
def test_with_configfile_and_cleanup_extra_directories_extends_default( self, tmp_path): # -- SETUP: setup_workdir(tmp_path, [ ".venv_CONFIG/.dir", "one.xxx/.dir", "more/two.zzz/.dir", ]) my_dir0 = tmp_path / ".venv_CONFIG" my_dir1 = tmp_path / "one.xxx" my_dir2 = tmp_path / "more/two.zzz" assert my_dir1.exists() and my_dir1.is_dir() assert my_dir2.exists() and my_dir2.is_dir() tasks_dir = tmp_path / "tasks.py" tasks_dir.write_text(TASKS_FILE_TEXT_USING_CLEANUP_MODULE_ONLY) config_dir = tmp_path / "invoke.yaml" config_dir.write_text(u""" cleanup: directories: - ".venv*" extra_directories: - "**/*.xxx" - "**/*.zzz" """) # -- EXECUTE AND VERIFY: with use_subprocess_coverage(tmp_path): with cd(str(tmp_path)): output = ensure_text(run_with_output("invoke cleanup.all")) assert not my_dir0.exists() assert not my_dir1.exists() assert not my_dir2.exists() expected0 = "RMTREE: .venv_CONFIG" expected1 = "RMTREE: one.xxx" expected2 = "RMTREE: more/two.zzz" assert expected0 in output assert expected1 in output assert expected2 in output
def test_with_matching_directory__should_skip_remove_and_showit_in_verbose_mode(self, tmp_path, capsys): # -- SETUP: setup_workdir(tmp_path, [ "one.xxx", "more/two.xxx/.dir" ]) my_file1 = tmp_path/"one.xxx" my_dir2 = tmp_path/"more/two.xxx" assert my_file1.exists() and my_file1.is_file() assert my_dir2.exists() and my_dir2.is_dir() # -- EXECUTE AND VERIFY: Best-effort, ignore read-only file(s) # with pytest.raises(OSError, match="Permission denied"): cwd = tmp_path cleanup_files(["**/*.xxx"], cwd, verbose=True) captured = capsys.readouterr() assert not my_file1.exists(), "OOPS: my_file1 was NOT_REMOVED" assert my_dir2.exists(), "OOPS: my_dir2 was REMOVED" # -- ONLY IN VERBOSE MODE: expected = "REMOVE: {0} (SKIPPED: Not a file)".format(my_dir2) assert expected in captured.out
def test_with_configfile_and_cleanup_extra_files_extends_default( self, tmp_path): # -- SETUP: setup_workdir(tmp_path, [ "DEFAULT_FILE.bak", "one.xxx", "more/two.zzz", ]) my_file0 = tmp_path / "DEFAULT_FILE.bak" my_file1 = tmp_path / "one.xxx" my_file2 = tmp_path / "more/two.zzz" assert my_file0.exists() and my_file0.is_file() assert my_file1.exists() and my_file1.is_file() assert my_file2.exists() and my_file2.is_file() tasks_file = tmp_path / "tasks.py" tasks_file.write_text(TASKS_FILE_TEXT_USING_CLEANUP_MODULE_ONLY) config_file = tmp_path / "invoke.yaml" config_file.write_text(u""" cleanup: extra_files: - "**/*.xxx" - "**/*.zzz" """) # -- EXECUTE AND VERIFY: output = run_with_output_in_directory(tmp_path) assert not my_file0.exists( ), "OOPS: DEFAULT:cleanup.files was NOT_REMOVED" assert not my_file1.exists() assert not my_file2.exists() expected0 = "REMOVE: DEFAULT_FILE.bak" expected1 = "REMOVE: one.xxx" expected2 = "REMOVE: more/two.zzz" assert expected0 in output assert expected1 in output assert expected2 in output
def test_skips_rmtree_that_contains_sys_executable(self, tmp_path, monkeypatch, capsys): """SKIP-SUICIDE in context of cleanup_dirs in virtual environment.""" setup_workdir(tmp_path, [ "foo/one.xxx/python_x.y/bin/python", ]) python_basedir = tmp_path / "foo/one.xxx/python_x.y" mock_sys_executable = python_basedir / "bin/python" mock_sys_executable = str(mock_sys_executable.absolute()) problematic_dir = "foo/one.xxx" with cd(str(tmp_path)): monkeypatch.setattr("sys.executable", mock_sys_executable) cleanup_dirs(["**/*.xxx"], dry_run=True) # pylint: disable=line-too-long captured = capsys.readouterr() print(captured.out) # expected = "SKIP-SUICIDE: 'foo/one.xxx' contains current python executable" expected1 = "SKIP-SUICIDE: '%s'" % problematic_dir expected2 = "SKIP-SUICIDE: '%s' contains current python executable" % problematic_dir assert expected1 in captured.out assert expected2 in captured.out