Automation Module¶
Automation and scheduling components for background processing.
Service Manager¶
service_manager
¶
Service manager for macOS launchd automation.
This module provides a high-level interface for installing, uninstalling, and managing the video converter launchd service on macOS.
SDS Reference: SDS-A01-002 SRS Reference: SRS-702 (Service Install/Uninstall)
Example
from video_converter.automation.service_manager import ServiceManager
manager = ServiceManager()
Install service to run daily at 3 AM¶
result = manager.install(hour=3, minute=0) print(result.message)
Check service status¶
status = manager.get_status() print(f"Installed: {status.is_installed}")
Uninstall service¶
result = manager.uninstall()
ServiceState
¶
Bases: Enum
State of the launchd service.
ServiceStatus
dataclass
¶
ServiceStatus(state, is_installed, is_loaded, is_running, pid=None, last_exit_status=None, plist_path=None, schedule=None, next_run=None)
Status information for the launchd service.
Attributes:
| Name | Type | Description |
|---|---|---|
state |
ServiceState
|
Current state of the service. |
is_installed |
bool
|
Whether the plist file exists. |
is_loaded |
bool
|
Whether the service is loaded in launchd. |
is_running |
bool
|
Whether the service is currently running. |
pid |
int | None
|
Process ID if running, None otherwise. |
last_exit_status |
int | None
|
Exit status from last run, None if never run. |
plist_path |
Path | None
|
Path to the plist file. |
schedule |
str | None
|
Human-readable schedule description. |
next_run |
datetime | None
|
Estimated next run time, None if not scheduled. |
ServiceResult
dataclass
¶
Result of a service operation.
Attributes:
| Name | Type | Description |
|---|---|---|
success |
bool
|
Whether the operation succeeded. |
message |
str
|
Human-readable result message. |
error |
str | None
|
Error message if failed, None otherwise. |
plist_path |
Path | None
|
Path to the plist file, if applicable. |
LastRunInfo
dataclass
¶
LastRunInfo(timestamp=None, success=None, videos_converted=0, storage_saved_bytes=0, error_message=None)
Information about the last service run.
Attributes:
| Name | Type | Description |
|---|---|---|
timestamp |
datetime | None
|
When the service last ran. |
success |
bool | None
|
Whether the last run was successful. |
videos_converted |
int
|
Number of videos converted in last run. |
storage_saved_bytes |
int
|
Bytes saved in last run. |
error_message |
str | None
|
Error message if last run failed. |
DetailedServiceStatus
dataclass
¶
DetailedServiceStatus(basic_status, next_run=None, next_run_relative='Unknown', last_run=LastRunInfo(), total_videos_converted=0, total_storage_saved_bytes=0, success_rate=0.0)
Extended status information including history and next run.
Attributes:
| Name | Type | Description |
|---|---|---|
basic_status |
ServiceStatus
|
Basic ServiceStatus information. |
next_run |
datetime | None
|
Estimated next run time. |
next_run_relative |
str
|
Human-readable next run description. |
last_run |
LastRunInfo
|
Information about the last run. |
total_videos_converted |
int
|
Total videos converted (all time). |
total_storage_saved_bytes |
int
|
Total storage saved (all time). |
success_rate |
float
|
Overall success rate (0.0-1.0). |
ServiceManager
¶
Manager for launchd service operations.
This class provides high-level operations for installing, uninstalling, and querying the status of the video converter launchd service.
Attributes:
| Name | Type | Description |
|---|---|---|
plist_path |
Path to the launchd plist file. |
|
log_dir |
Directory for service log files. |
Initialize the service manager.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
plist_path
|
Path | None
|
Path to plist file. Defaults to LaunchAgents directory. |
None
|
log_dir
|
Path | None
|
Directory for log files. |
None
|
Source code in src/video_converter/automation/service_manager.py
install
¶
Install the launchd service.
This method generates a plist file and loads it into launchd. If the service is already installed, it will be updated if force=True.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hour
|
int | None
|
Hour to run (0-23). None for watch-only mode. |
3
|
minute
|
int
|
Minute to run (0-59). |
0
|
weekday
|
int | None
|
Day of week (0=Sunday). None for daily. |
None
|
watch_paths
|
list[Path] | None
|
Folders to watch for changes. |
None
|
run_at_load
|
bool
|
Whether to run immediately when loaded. |
False
|
force
|
bool
|
If True, reinstall even if already installed. |
False
|
Returns:
| Type | Description |
|---|---|
ServiceResult
|
ServiceResult with success status and message. |
Example
manager = ServiceManager() result = manager.install(hour=3, minute=0) if result.success: ... print("Service installed successfully")
Source code in src/video_converter/automation/service_manager.py
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | |
uninstall
¶
Uninstall the launchd service.
This method unloads the service from launchd and removes the plist file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
remove_logs
|
bool
|
If True, also remove log files. |
False
|
Returns:
| Type | Description |
|---|---|
ServiceResult
|
ServiceResult with success status and message. |
Example
manager = ServiceManager() result = manager.uninstall() if result.success: ... print("Service uninstalled successfully")
Source code in src/video_converter/automation/service_manager.py
get_status
¶
Get the current status of the service.
Returns:
| Type | Description |
|---|---|
ServiceStatus
|
ServiceStatus with detailed status information. |
Example
manager = ServiceManager() status = manager.get_status() print(f"Installed: {status.is_installed}") print(f"Running: {status.is_running}")
Source code in src/video_converter/automation/service_manager.py
start
¶
Manually start the service.
This triggers an immediate run of the service, regardless of schedule.
Returns:
| Type | Description |
|---|---|
ServiceResult
|
ServiceResult with success status and message. |
Source code in src/video_converter/automation/service_manager.py
stop
¶
Stop the currently running service.
Returns:
| Type | Description |
|---|---|
ServiceResult
|
ServiceResult with success status and message. |
Source code in src/video_converter/automation/service_manager.py
load
¶
Load the service into launchd.
This is the public wrapper for loading the service plist into launchd. The service must be installed (plist file exists) before loading.
Returns:
| Type | Description |
|---|---|
ServiceResult
|
ServiceResult with success status and message. |
Example
manager = ServiceManager() result = manager.load() if result.success: ... print("Service loaded into launchd")
Source code in src/video_converter/automation/service_manager.py
unload
¶
Unload the service from launchd.
This is the public wrapper for unloading the service from launchd. The service will stop running but the plist file remains installed.
Returns:
| Type | Description |
|---|---|
ServiceResult
|
ServiceResult with success status and message. |
Example
manager = ServiceManager() result = manager.unload() if result.success: ... print("Service unloaded from launchd")
Source code in src/video_converter/automation/service_manager.py
restart
¶
Restart the service.
Unloads and reloads the service from launchd.
Returns:
| Type | Description |
|---|---|
ServiceResult
|
ServiceResult with success status and message. |
Example
manager = ServiceManager() result = manager.restart() if result.success: ... print("Service restarted")
Source code in src/video_converter/automation/service_manager.py
get_log_paths
¶
Get paths to stdout and stderr log files.
Returns:
| Type | Description |
|---|---|
tuple[Path, Path]
|
Tuple of (stdout_path, stderr_path). |
Source code in src/video_converter/automation/service_manager.py
read_logs
¶
Read recent log entries.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lines
|
int
|
Number of lines to read from each log file. |
50
|
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
Dictionary with 'stdout' and 'stderr' log contents. |
Source code in src/video_converter/automation/service_manager.py
calculate_next_run
¶
Calculate the next scheduled run time.
Parses the plist file to determine when the service will next run based on StartCalendarInterval settings.
Returns:
| Type | Description |
|---|---|
datetime | None
|
Tuple of (next_run_datetime, human_readable_description). |
str
|
Returns (None, "Not scheduled") if no schedule is configured. |
Example
manager = ServiceManager() next_run, description = manager.calculate_next_run() print(f"Next run: {description}")
Source code in src/video_converter/automation/service_manager.py
get_last_run_info
¶
Get information about the last service run.
Determines last run time from log file modification times and parses log content for success/failure information.
Returns:
| Type | Description |
|---|---|
LastRunInfo
|
LastRunInfo with timestamp, success status, and statistics. |
Example
manager = ServiceManager() last_run = manager.get_last_run_info() print(f"Last run: {last_run.relative_time} ({last_run.result_text})")
Source code in src/video_converter/automation/service_manager.py
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 | |
get_detailed_status
¶
Get comprehensive status including history and scheduling.
Combines basic service status with conversion history statistics and next run calculations.
Returns:
| Type | Description |
|---|---|
DetailedServiceStatus
|
DetailedServiceStatus with all status information. |
Example
manager = ServiceManager() status = manager.get_detailed_status() print(f"Status: {status.basic_status.state}") print(f"Next run: {status.next_run_relative}") print(f"Last run: {status.last_run.relative_time}") print(f"Total converted: {status.total_videos_converted}")
Source code in src/video_converter/automation/service_manager.py
format_bytes
¶
Format bytes into human-readable string.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bytes_value
|
int
|
Number of bytes. |
required |
Returns:
| Type | Description |
|---|---|
str
|
Formatted string like "1.5 GB" or "256 MB". |
Source code in src/video_converter/automation/service_manager.py
Launchd¶
launchd
¶
launchd plist generator for macOS automation.
This module generates launchd plist files to enable scheduled automatic video conversion on macOS. It supports time-based scheduling (StartCalendarInterval) and folder-based triggers (WatchPaths).
SDS Reference: SDS-A01-001 SRS Reference: SRS-701 (launchd Integration)
Example
from video_converter.automation.launchd import LaunchdPlistGenerator from video_converter.core.config import Config
config = Config.load() generator = LaunchdPlistGenerator(config)
Generate plist for daily run at 3 AM¶
plist = generator.generate_plist(hour=3, minute=0) generator.write_plist(plist)
Generate plist with folder watching¶
plist = generator.generate_plist(watch_paths=[Path("~/Videos/Import")])
LaunchdSchedule
dataclass
¶
Schedule configuration for launchd service.
Attributes:
| Name | Type | Description |
|---|---|---|
hour |
int | None
|
Hour to run (0-23). None for watch-only mode. |
minute |
int
|
Minute to run (0-59). |
weekday |
int | None
|
Day of week (0=Sunday, 1=Monday, ..., 6=Saturday). None for daily schedule. |
__post_init__
¶
Validate schedule values.
Source code in src/video_converter/automation/launchd.py
to_calendar_interval
¶
Convert to StartCalendarInterval dictionary.
Returns:
| Type | Description |
|---|---|
dict[str, int]
|
Dictionary with Hour, Minute, and optionally Weekday. |
Source code in src/video_converter/automation/launchd.py
LaunchdConfig
dataclass
¶
LaunchdConfig(label=SERVICE_LABEL, program_args=list(), schedule=None, watch_paths=list(), working_directory=None, environment=dict(), stdout_path=None, stderr_path=None, run_at_load=False, keep_alive=False)
Configuration for launchd plist generation.
Attributes:
| Name | Type | Description |
|---|---|---|
label |
str
|
Service identifier (e.g., "com.videoconverter.daily"). |
program_args |
list[str]
|
Command line arguments for the service. |
schedule |
LaunchdSchedule | None
|
Time-based schedule (StartCalendarInterval). |
watch_paths |
list[Path]
|
Folder paths to watch for changes (WatchPaths). |
working_directory |
Path | None
|
Working directory for the service. |
environment |
dict[str, str]
|
Environment variables to set. |
stdout_path |
Path | None
|
Path for stdout log file. |
stderr_path |
Path | None
|
Path for stderr log file. |
run_at_load |
bool
|
Whether to run immediately when loaded. |
keep_alive |
bool
|
Whether to restart if process exits. |
__post_init__
¶
LaunchdPlistGenerator
¶
Generator for launchd plist files.
This class creates valid launchd plist XML files for scheduling automatic video conversion on macOS.
Attributes:
| Name | Type | Description |
|---|---|---|
python_path |
Path to Python interpreter. |
|
module_name |
Python module to execute. |
|
command |
CLI command to run (e.g., "run"). |
|
log_dir |
Directory for log files. |
Initialize the plist generator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
python_path
|
Path | None
|
Path to Python interpreter. Auto-detected if None. |
None
|
module_name
|
str
|
Python module to execute. |
'video_converter'
|
command
|
str
|
CLI command to run. |
'run'
|
log_dir
|
Path | None
|
Directory for log files. |
None
|
Source code in src/video_converter/automation/launchd.py
generate_config
¶
generate_config(hour=3, minute=0, weekday=None, watch_paths=None, run_at_load=False, extra_args=None)
Generate launchd configuration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hour
|
int | None
|
Hour to run (0-23). None for watch-only mode. |
3
|
minute
|
int
|
Minute to run (0-59). |
0
|
weekday
|
int | None
|
Day of week (0=Sunday). None for daily. |
None
|
watch_paths
|
list[Path] | None
|
Folders to watch for changes. |
None
|
run_at_load
|
bool
|
Whether to run immediately when loaded. |
False
|
extra_args
|
list[str] | None
|
Additional CLI arguments. |
None
|
Returns:
| Type | Description |
|---|---|
LaunchdConfig
|
LaunchdConfig with all settings. |
Source code in src/video_converter/automation/launchd.py
generate_plist
¶
generate_plist(config=None, hour=3, minute=0, weekday=None, watch_paths=None, run_at_load=False, extra_args=None)
Generate launchd plist dictionary.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
LaunchdConfig | None
|
Pre-built configuration. If None, built from other args. |
None
|
hour
|
int | None
|
Hour to run (0-23). None for watch-only mode. |
3
|
minute
|
int
|
Minute to run (0-59). |
0
|
weekday
|
int | None
|
Day of week (0=Sunday). None for daily. |
None
|
watch_paths
|
list[Path] | None
|
Folders to watch for changes. |
None
|
run_at_load
|
bool
|
Whether to run immediately when loaded. |
False
|
extra_args
|
list[str] | None
|
Additional CLI arguments. |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dictionary representation of plist. |
Example
generator = LaunchdPlistGenerator() plist = generator.generate_plist(hour=3, minute=0)
plist is ready for writing with plistlib¶
Source code in src/video_converter/automation/launchd.py
plist_to_xml
¶
Convert plist dictionary to XML bytes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
plist
|
dict[str, Any]
|
Plist dictionary. |
required |
Returns:
| Type | Description |
|---|---|
bytes
|
XML representation as bytes. |
Source code in src/video_converter/automation/launchd.py
write_plist
¶
Write plist to file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
plist
|
dict[str, Any]
|
Plist dictionary. |
required |
output_path
|
Path | None
|
Path to write plist. Defaults to LaunchAgents dir. |
None
|
Returns:
| Type | Description |
|---|---|
Path
|
Path to the written plist file. |
Raises:
| Type | Description |
|---|---|
IOError
|
If file cannot be written. |
Source code in src/video_converter/automation/launchd.py
get_plist_path
¶
Get the default plist file path.
Returns:
| Type | Description |
|---|---|
Path
|
Path to the plist file. |
validate_plist_syntax
¶
Validate plist file syntax using plutil.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
plist_path
|
Path
|
Path to plist file. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if plist is valid, False otherwise. |
Source code in src/video_converter/automation/launchd.py
generate_daily_plist
¶
Convenience function to generate a daily schedule plist.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hour
|
int
|
Hour to run (0-23). |
3
|
minute
|
int
|
Minute to run (0-59). |
0
|
python_path
|
Path | None
|
Path to Python interpreter. |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Plist dictionary. |
Example
plist = generate_daily_plist(hour=3, minute=0)
Write to file¶
generator = LaunchdPlistGenerator() generator.write_plist(plist)
Source code in src/video_converter/automation/launchd.py
generate_watch_plist
¶
Convenience function to generate a folder-watching plist.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
watch_paths
|
list[Path]
|
List of folders to watch. |
required |
python_path
|
Path | None
|
Path to Python interpreter. |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Plist dictionary. |
Example
plist = generate_watch_plist([Path("~/Videos/Import")]) generator = LaunchdPlistGenerator() generator.write_plist(plist)
Source code in src/video_converter/automation/launchd.py
Notification¶
notification
¶
macOS Notification Center integration for video conversion alerts.
This module provides integration with macOS Notification Center to send alerts for conversion completion, errors, and summary statistics.
SDS Reference: SDS-A01-002 SRS Reference: SRS-801 (macOS Notification Integration)
Example
from video_converter.automation.notification import NotificationManager from video_converter.core.types import ConversionReport
manager = NotificationManager()
Send a simple notification¶
manager.send_notification( ... title="Conversion Complete", ... body="12 videos converted, 8.5 GB saved", ... )
Send notification from a report¶
manager.send_batch_notification(report)
NotificationType
¶
Bases: Enum
Type of notification to send.
Attributes:
| Name | Type | Description |
|---|---|---|
SUCCESS |
All conversions completed successfully. |
|
PARTIAL |
Some conversions completed with errors. |
|
FAILURE |
All conversions failed or critical error occurred. |
|
INFO |
Informational notification. |
NotificationConfig
dataclass
¶
Configuration for notification behavior.
Attributes:
| Name | Type | Description |
|---|---|---|
enabled |
bool
|
Whether notifications are enabled. |
sound |
bool
|
Whether to play sound with notification. |
sound_name |
str
|
Name of the sound to play (macOS system sound). |
group_id |
str
|
Optional group identifier for notification grouping. |
NotificationResult
dataclass
¶
Result of a notification send attempt.
Attributes:
| Name | Type | Description |
|---|---|---|
success |
bool
|
Whether the notification was sent successfully. |
error_message |
str | None
|
Error message if sending failed. |
NotificationManager
¶
Manager for sending macOS Notification Center notifications.
This class provides methods to send notifications for various video conversion events including batch completion, errors, and progress milestones.
Attributes:
| Name | Type | Description |
|---|---|---|
config |
Notification configuration settings. |
Initialize the notification manager.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
NotificationConfig | None
|
Optional configuration. Uses defaults if not provided. |
None
|
Source code in src/video_converter/automation/notification.py
is_available
¶
Check if notifications are available on this system.
Returns:
| Type | Description |
|---|---|
bool
|
True if notifications can be sent, False otherwise. |
Source code in src/video_converter/automation/notification.py
send_notification
¶
Send a notification to macOS Notification Center.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
title
|
str
|
The notification title. |
required |
body
|
str
|
The notification body text. |
required |
sound
|
bool | None
|
Whether to play sound. Uses config default if None. |
None
|
subtitle
|
str | None
|
Optional subtitle for the notification. |
None
|
Returns:
| Type | Description |
|---|---|
NotificationResult
|
NotificationResult indicating success or failure. |
Source code in src/video_converter/automation/notification.py
send_batch_notification
¶
Send notification based on batch conversion report.
Automatically determines notification type and formats the message based on conversion results.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
report
|
ConversionReport
|
The conversion report to notify about. |
required |
Returns:
| Type | Description |
|---|---|
NotificationResult
|
NotificationResult indicating success or failure. |
Source code in src/video_converter/automation/notification.py
send_success_notification
¶
Send a success notification with statistics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
videos_converted
|
int
|
Number of videos converted. |
required |
size_saved
|
int
|
Total bytes saved. |
required |
Returns:
| Type | Description |
|---|---|
NotificationResult
|
NotificationResult indicating success or failure. |
Source code in src/video_converter/automation/notification.py
send_error_notification
¶
Send an error notification.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
error_message
|
str
|
The error message to display. |
required |
file_name
|
str | None
|
Optional file name that caused the error. |
None
|
Returns:
| Type | Description |
|---|---|
NotificationResult
|
NotificationResult indicating success or failure. |
Source code in src/video_converter/automation/notification.py
send_partial_notification
¶
Send a partial success notification.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
succeeded
|
int
|
Number of successful conversions. |
required |
failed
|
int
|
Number of failed conversions. |
required |
Returns:
| Type | Description |
|---|---|
NotificationResult
|
NotificationResult indicating success or failure. |
Source code in src/video_converter/automation/notification.py
send_notification
¶
Convenience function to send a simple notification.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
title
|
str
|
The notification title. |
required |
body
|
str
|
The notification body text. |
required |
sound
|
bool
|
Whether to play sound. |
True
|
Returns:
| Type | Description |
|---|---|
NotificationResult
|
NotificationResult indicating success or failure. |
Example
result = send_notification( ... title="Conversion Complete", ... body="12 videos converted", ... )