feat(cleaner): ✨ add command prune

this new command will be called by cron-like process to clean purge old logs and old mails. All files were formatted and mail_utils was renamed in utils since it now defines utility function not only for mail functions.
This commit is contained in:
2026-09-25 16:30:45 +02:00
parent 63c4d1387e
commit 02e85ddbfd
20 changed files with 471 additions and 164 deletions
+28 -44
View File
@@ -8,7 +8,7 @@ from unittest.mock import MagicMock
from logwatcher import __version__
from logwatcher.cli import _get_files_from_dir, _is_log_file, app
from logwatcher.cli import _get_files_from_dir, app
runner = CliRunner()
@@ -62,33 +62,9 @@ def test_version_cli():
assert f"logwatcher version: {__version__}" in result.output
def test_is_log_file(tmp_path: Path):
"""Assert only .log, .txt or file without extensions are valid.
Args:
tmp_path: Temporary root path for testing results
"""
# set up files
Path(tmp_path / "a.log").touch()
Path(tmp_path / "a.txt").touch()
Path(tmp_path / "a.csv").touch()
Path(tmp_path / "a.py").touch()
Path(tmp_path / "a").touch()
Path(tmp_path / "a.pdf").touch()
# test
assert _is_log_file(Path(tmp_path / "a.log"))
assert _is_log_file(Path(tmp_path / "a.txt"))
assert _is_log_file(Path(tmp_path / "a")) # without extensions
assert not _is_log_file(Path(tmp_path / "a.csv"))
assert not _is_log_file(Path(tmp_path / "a.py"))
assert not _is_log_file(Path(tmp_path / "a.pdf"))
def test_get_files_from_dir_empty_dir(tmp_path: Path):
"""Assert that a non-existing directory (or wrong path) cannot be given as a working input directory.
Assert that everything works even if the directory is empty.
Args:
@@ -154,7 +130,7 @@ def test_cli_from_files_input_files_and_input_dir(output_path: Path):
def test_cli_from_files_neither_input_files_nor_input_dir():
"""Test calling cli without providing input files or input dir options.
Must return an error on provided parameters (BadParameter = exit code 2)
"""
@@ -163,7 +139,9 @@ def test_cli_from_files_neither_input_files_nor_input_dir():
assert "Either input_files or input_dir must be provided" in results.output
def test_cli_from_files_bad_input_file(tmp_path: Path, output_path: Path, invalid_log_dir: Path):
def test_cli_from_files_bad_input_file(
tmp_path: Path, output_path: Path, invalid_log_dir: Path
):
"""Test calling cli with bad input file (directory instead of file).
Must return an exit code at 1 and the ValueError exception raised
@@ -277,7 +255,7 @@ def test_cli_from_files_input_files_or_input_dir(
def test_cli_from_files_input_files_one_file(valid_log_dir: Path, output_path: Path):
"""Assert that CLI can analyze a single valid file.
Args:
valid_log_dir: Fixture of directory of valid logs
output_path: Fixture of directory receiving all file generated during process.
@@ -405,22 +383,22 @@ def test_cli_from_files_valid_logs(output_path: Path, valid_log_dir: Path):
def test_cli_from_mails_no_output_dir(monkeypatch, make_mock_account):
"""Assert everything works when no output_path is provided.
Must use "output/" directory, located in project root.
"""
messages = [
Message(subject="subject test 1", text_body="body test 1"),
Message(subject="subject test 2", text_body="body test 2"),
Message(subject="subject test 3", text_body="body test 3")
Message(subject="subject test 3", text_body="body test 3"),
]
with monkeypatch.context() as m:
m.setattr("logwatcher.cli.connect_to_mailbox", lambda: make_mock_account(messages=messages, analyzed_folder="Analyzed"))
m.setattr(
"logwatcher.cli.connect_to_mailbox",
lambda: make_mock_account(messages=messages, analyzed_folder="Analyzed"),
)
m.setattr("logwatcher.notifier.Message.send", MagicMock(return_value=None))
arguments = ["from-mails"]
results = runner.invoke(app, arguments)
assert results.exit_code == 0
@@ -428,7 +406,7 @@ def test_cli_from_mails_no_output_dir(monkeypatch, make_mock_account):
def test_cli_from_mails_invalid_output_dir(tmp_path, monkeypatch):
"""Assert that if output_dir is a file, raise an error.
Args:
tmp_path: path where to store temporarily output files
monkeypatch: used to fake a context and method calls
@@ -442,9 +420,12 @@ def test_cli_from_mails_invalid_output_dir(tmp_path, monkeypatch):
]
with monkeypatch.context() as m:
m.setattr("logwatcher.cli.connect_to_mailbox", lambda: make_mock_account(messages=messages, analyzed_folder="Analyzed"))
m.setattr(
"logwatcher.cli.connect_to_mailbox",
lambda: make_mock_account(messages=messages, analyzed_folder="Analyzed"),
)
m.setattr("logwatcher.notifier.Message.send", MagicMock(return_value=None))
arguments = ["from-mails", "--output-dir", bad_output_dir]
results = runner.invoke(app, arguments)
assert results.exit_code != 0
@@ -452,7 +433,7 @@ def test_cli_from_mails_invalid_output_dir(tmp_path, monkeypatch):
def test_cli_from_mails_valid_output_dir(tmp_path, monkeypatch, make_mock_account):
"""Assert everything works when a valid output_path is provided.
Args:
tmp_path: path where to store temporarily output files
monkeypatch: used to fake a context and method calls
@@ -464,16 +445,19 @@ def test_cli_from_mails_valid_output_dir(tmp_path, monkeypatch, make_mock_accoun
messages = [
Message(subject="subject test 1", text_body="body test 1"),
Message(subject="subject test 2", text_body="body test 2"),
Message(subject="subject test 3", text_body="body test 3")
Message(subject="subject test 3", text_body="body test 3"),
]
with monkeypatch.context() as m:
m.setattr("logwatcher.cli.connect_to_mailbox", lambda: make_mock_account(messages=messages, analyzed_folder="Analyzed"))
m.setattr(
"logwatcher.cli.connect_to_mailbox",
lambda: make_mock_account(messages=messages, analyzed_folder="Analyzed"),
)
m.setattr("logwatcher.notifier.Message.send", MagicMock(return_value=None))
arguments = ["from-mails", "--output-dir", output_path]
results = runner.invoke(app, arguments)
assert results.exit_code == 0
output_children = list(output_path.iterdir())
expected = ["n2.log", "all.log", "other.log"]