diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 465f339..88c5f02 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -8,7 +8,7 @@ This guide will help you get started. 1. Clone the repository: ```bash - git clone https://github.com/your-username/aeonview.git + git clone https://github.com/ivuorinen/aeonview.git cd aeonview ``` @@ -17,7 +17,7 @@ This guide will help you get started. ```bash python3 -m venv venv source venv/bin/activate - pip install -r dev-requirements.txt + pip install -r requirements.txt ``` 3. Install pre-commit hooks: diff --git a/README.md b/README.md index 0401d7a..8516c74 100644 --- a/README.md +++ b/README.md @@ -14,14 +14,14 @@ Includes developer tooling and tests. [![CI][ci-b]][ci-l] [![ruff][cc-b]][cc-l] [![MIT][lm-b]][lm-l] -Low quality sample: [aeonview 2min preview/Tampere Jan. 2008][sample] +Low-quality sample: [aeonview 2min preview/Tampere Jan. 2008][sample] ## Features - Timelapse image capture (`--mode image`) - Video generation (`--mode video`) - Support for daily, monthly, yearly video runs *(daily implemented)* -- Uses `ffmpeg` and `curl` +- Uses `ffmpeg` and Python `requests` - Fully tested with `pytest` - Linting and formatting via `ruff` - Pre-commit hooks and CI-ready @@ -29,10 +29,9 @@ Low quality sample: [aeonview 2min preview/Tampere Jan. 2008][sample] ## Requirements - Python 3.13+ -- `ffmpeg` and `curl` (system tools) +- `ffmpeg` (system tool) - lots of hard drive space - Optional: `pyenv` for managing Python versions - (see `pyenv_requirements`) ## Installation diff --git a/aeonview.py b/aeonview.py index 765fdd9..ecf43e2 100644 --- a/aeonview.py +++ b/aeonview.py @@ -3,7 +3,6 @@ from __future__ import annotations import argparse import hashlib import logging -import os import subprocess import sys from datetime import datetime, timedelta @@ -240,7 +239,10 @@ class AeonViewVideos: if not self.simulate: logging.info("Running ffmpeg command: %s", " ".join(ffmpeg_cmd)) - if not os.path.exists(output_dir): + if not input_dir.exists(): + logging.error("Input directory %s does not exist", input_dir) + sys.exit(1) + if not output_dir.exists(): AeonViewHelpers.mkdir_p(output_dir) subprocess.run(ffmpeg_cmd, check=True) logging.info( @@ -481,7 +483,7 @@ class AeonViewApp: self.base_path, self.args.project ) - if not os.path.exists(project_path): + if not project_path.exists(): logging.error("Project path %s does not exist.", project_path) sys.exit(1) diff --git a/aeonview_test.py b/aeonview_test.py index 300cd09..8f757bd 100644 --- a/aeonview_test.py +++ b/aeonview_test.py @@ -174,25 +174,30 @@ def test_download_image_failure(mock_get): avi.download_image(destination) -@mock.patch("aeonview.AeonViewHelpers.mkdir_p") @mock.patch("subprocess.run") -def test_generate_daily_video(mock_subprocess_run, mock_mkdir_p): - args = argparse.Namespace( - simulate=False, - fps=10, - day="01", - month="04", - year="2025" - ) - avv = AeonViewVideos(default_test_path, args) - with mock.patch("aeonview.logging.info") as log: - avv.generate_daily_video() - last_call_args = log.call_args_list[-1][0] - assert last_call_args[0] == "%s: %s" - assert last_call_args[1] == AeonViewMessages.VIDEO_GENERATION_SUCCESS - assert last_call_args[2] == default_test_path / "vid/2025-04/01.mp4" - - mock_mkdir_p.assert_called() +def test_generate_daily_video(mock_subprocess_run): + with tempfile.TemporaryDirectory() as tmp: + project_path = Path(tmp).resolve() + args = argparse.Namespace( + simulate=False, + fps=10, + day="01", + month="04", + year="2025" + ) + avv = AeonViewVideos(project_path, args) + # Create input directory so the existence check passes + (project_path / "img" / "2025-04" / "01").mkdir(parents=True) + with mock.patch("aeonview.AeonViewHelpers.mkdir_p") as mock_mkdir_p: + with mock.patch("aeonview.logging.info") as log: + avv.generate_daily_video() + last_call_args = log.call_args_list[-1][0] + assert last_call_args[0] == "%s: %s" + assert last_call_args[1] == AeonViewMessages.VIDEO_GENERATION_SUCCESS + assert last_call_args[2] == ( + project_path / "vid" / "2025-04" / "01.mp4" + ) + mock_mkdir_p.assert_called() mock_subprocess_run.assert_called() diff --git a/requests.py b/requests.py deleted file mode 100644 index 832846a..0000000 --- a/requests.py +++ /dev/null @@ -1,9 +0,0 @@ -class Response: - def __init__(self, status_code=200): - self.status_code = status_code - - def iter_content(self, chunk_size=1024): - return iter([]) - -def get(url, stream=False, timeout=0): - raise NotImplementedError("requests.get is not implemented")