YT-DL-CLI Video downloader documentation¶
Main Module¶
YT-DL-CLI Video Downloader Main Application Module.
This module contains the primary VideoDownloader class that serves as the main orchestrator for the entire video downloading process. It integrates all components of the application including configuration management, dependency injection, asynchronous orchestration, and comprehensive error handling.
The module is designed with a clean architecture approach, separating concerns between configuration, logging, orchestration, and execution. It provides a high-level interface that abstracts away the complexity of concurrent downloads, internationalization, and error management.
- Key Features:
Command-line argument parsing and configuration management
Dependency injection for clean component integration
Asynchronous download orchestration for optimal performance
Comprehensive error handling with user-friendly messages
Internationalization support for multi-language environments
Graceful handling of user interruptions and system errors
- Architecture:
The module follows the dependency injection pattern to ensure loose coupling between components. The VideoDownloader class acts as a facade that coordinates between different subsystems without being tightly coupled to their implementations.
The application architecture consists of several layers:
Presentation Layer (CLI Interface): - Command-line argument parsing - User interaction and feedback - Progress reporting and error messages
Application Layer (Main Orchestration): - VideoDownloader class (main entry point) - Configuration management and validation - High-level workflow coordination
Domain Layer (Business Logic): - AsyncOrchestrator for concurrent operations - Download core functionality - Business rules and validation
Infrastructure Layer (External Dependencies): - File system operations - Network communication - Logging and monitoring - Internationalization services
- Design Patterns:
Facade Pattern: VideoDownloader provides simplified interface to complex subsystems
Dependency Injection: Promotes loose coupling and enhances testability
Context Manager: Ensures proper resource management and cleanup
Observer Pattern: Progress tracking and event notification
Strategy Pattern: Multiple download strategies and quality options
- Error Handling Strategy:
The module implements a comprehensive error handling approach:
Graceful Degradation: Continues operation when possible, falls back to defaults
User-Friendly Messages: Translates technical errors into understandable feedback
Logging Hierarchy: Different log levels for different audiences (user vs developer)
Resource Cleanup: Ensures proper cleanup even in error scenarios
Interruption Handling: Responds appropriately to user cancellation requests
- Performance Considerations:
Asynchronous I/O operations to prevent blocking
Concurrent downloads with configurable limits
Memory-efficient streaming for large files
Progress tracking without performance impact
Lazy loading of heavy dependencies
- Internationalization:
The module supports multiple languages through the i18n system: - Dynamic language detection from system locale - Runtime language switching capability - Localized error messages and user feedback - Cultural adaptation of date/time formats - Support for right-to-left languages
- Security Considerations:
Input validation for URLs and file paths
Safe file naming to prevent directory traversal
Secure temporary file handling
Network request validation and sanitization
Proper handling of sensitive configuration data
- Example Usage:
Command-line usage:
$ python main.py –url “https://youtube.com/watch?v=example” –quality 720p $ python main.py –playlist “https://youtube.com/playlist?list=example” –format mp3 $ python main.py –url “https://youtube.com/watch?v=example” –save-dir “/custom/path”
Programmatic usage:
>>> from main import VideoDownloader >>> >>> # Basic usage with defaults >>> downloader = VideoDownloader() >>> downloader.download() >>> >>> # Custom configuration >>> from yt_dl_cli.config.config import Config >>> config = Config(save_dir="/downloads", quality="1080p", format="mp4") >>> downloader = VideoDownloader(config=config) >>> downloader.download() >>> >>> # With custom logger and language >>> import logging >>> logger = logging.getLogger("custom_downloader") >>> downloader = VideoDownloader(config=config, logger=logger, language="ru") >>> downloader.download()
- Module Dependencies:
- Core Dependencies:
asyncio: Asynchronous I/O operations and event loop management
logging: Comprehensive logging infrastructure
traceback: Exception tracking and debugging information
typing: Type hints for better code documentation and IDE support
- Application Dependencies:
yt_dl_cli.config.config: Configuration management and validation
yt_dl_cli.utils.logger: Logger factory and configuration utilities
yt_dl_cli.core.orchestration: Asynchronous orchestration and DI container
yt_dl_cli.utils.parser: Command-line argument parsing utilities
yt_dl_cli.i18n.init: Internationalization initialization
yt_dl_cli.i18n.messages: Localized message management
- Testing:
The module is designed with testability in mind: - Dependency injection allows for easy mocking - Separation of concerns enables unit testing of individual components - Error handling can be tested through exception simulation - Configuration can be provided programmatically for test scenarios
- Compatibility:
Python 3.8+: Utilizes modern async/await syntax and type hints
Cross-platform: Works on Windows, macOS, and Linux
Unicode support: Handles international characters in filenames and paths
Network protocols: Supports HTTP/HTTPS with proxy configuration
Author: Oleksandr Kharhenko License: MIT Created: 2025 Last Modified: 20245
- See Also:
yt_dl_cli.config.config: Configuration management documentation
yt_dl_cli.core.orchestration: Asynchronous orchestration details
yt_dl_cli.utils.logger: Logging configuration and best practices
yt_dl_cli.i18n: Internationalization and localization guide
- class yt_dl_cli.main.VideoDownloader(config: Config | None = None, logger: ILogger | None = None, language: str | None = None)¶
Bases:
objectMain orchestrator class for the YouTube video downloading application.
This class serves as the primary entry point and coordinator for the entire download process. It encapsulates the complexity of managing configuration, dependency injection, asynchronous orchestration, and error handling while providing a simple interface for initiating downloads.
The class follows the facade pattern, providing a simplified interface to a complex subsystem of downloaders, parsers, loggers, and orchestrators. It ensures proper initialization order, resource management, and graceful error handling throughout the application lifecycle.
- Responsibilities:
Parse and validate command-line arguments
Initialize configuration and logging systems
Create and configure the dependency injection container
Orchestrate asynchronous download operations
Handle user interruptions and system errors gracefully
Manage resource cleanup and proper shutdown procedures
- Design Patterns:
Facade: Simplifies interaction with complex subsystems
Dependency Injection: Promotes loose coupling and testability
Context Manager: Ensures proper resource management
- Thread Safety:
This class is not thread-safe by design. Each instance should be used in a single thread context. For concurrent operations, the class delegates to AsyncOrchestrator which handles async/await patterns.
- Attributes:
- config (Config): Application configuration object containing all
settings for download operations, paths, and preferences.
- logger (logging.Logger): Configured logger instance for the application,
set up with appropriate handlers and formatters.
- Example:
Basic usage with default configuration:
>>> downloader = VideoDownloader() >>> downloader.download()
Usage with custom configuration:
>>> custom_config = Config(save_dir="/custom/path", quality="1080p") >>> custom_logger = logging.getLogger("custom") >>> downloader = VideoDownloader(config=custom_config, logger=custom_logger) >>> downloader.download()
- See Also:
Config: Configuration management class AsyncOrchestrator: Handles concurrent download operations DIContainer: Dependency injection container for component creation LoggerFactory: Factory for creating configured logger instances
- download() None¶
Execute the complete video download process with comprehensive error handling.
This method orchestrates the entire download workflow from initialization to completion. It serves as the main entry point for the download process, coordinating between multiple subsystems including dependency injection, asynchronous orchestration, resource management, and error handling.
The method implements a sophisticated error handling strategy that provides different responses for different types of failures, ensuring graceful degradation and proper user feedback. It uses context managers to guarantee resource cleanup regardless of how the process terminates.
- Process Architecture:
The download process follows a well-defined workflow:
Dependency Resolution: Creates the downloader core through the dependency injection container, ensuring all required components are properly initialized and configured.
Orchestrator Setup: Initializes the AsyncOrchestrator with the core components and configuration, preparing for concurrent operations.
Resource Management: Enters a context manager that ensures proper resource allocation and cleanup, including file handles, network connections, and temporary files.
Asynchronous Execution: Launches the main download orchestration using asyncio, enabling concurrent downloads and efficient I/O operations.
Completion Handling: Manages successful completion, user interruption, or error scenarios with appropriate logging and cleanup procedures.
- Error Handling Strategy:
The method implements a multi-layered error handling approach:
User Interruption (KeyboardInterrupt): Caught when the user presses Ctrl+C or sends SIGINT. Logs a localized warning message and performs graceful shutdown, allowing for cleanup of partial downloads and temporary files.
Critical System Errors (Exception): Catches all other unexpected exceptions, logs them as critical errors with full stack traces for debugging, and terminates the application with a non-zero exit code to indicate failure to calling processes.
Resource Management: The context manager pattern ensures that resources are properly cleaned up even if exceptions occur during the download process, preventing resource leaks and corruption.
- Concurrency and Performance:
Utilizes asyncio event loop for efficient concurrent operations
Delegates heavy I/O operations to specialized async components
Implements proper backpressure handling to prevent memory exhaustion
Provides real-time progress tracking without performance overhead
Manages connection pooling and rate limiting for optimal throughput
- Returns:
- None: This method operates through side effects and does not return
a value. Success is indicated by completion without exceptions, while failures are communicated through logging, user messages, and appropriate exit codes for process management.
- Raises:
- SystemExit: May be raised by underlying components for critical errors
that require immediate application termination. This typically occurs for configuration errors, permission issues, or unrecoverable system states. The exit code indicates the type of failure for process management and scripting.
- Side Effects:
- File System:
Creates downloaded video/audio files in the configured directory
Generates temporary files during the download process
Creates and updates log files with operation details
May create directory structures for organized storage
- Network:
Establishes connections to video hosting services
Downloads video metadata and content streams
May configure proxy settings and authentication
Implements rate limiting and retry mechanisms
- User Interface:
Displays progress indicators and download statistics
Shows real-time status updates and completion notifications
Provides error messages and troubleshooting information
Updates terminal title and status (where supported)
- System Resources:
Manages memory usage for concurrent operations
Utilizes available CPU cores for parallel processing
Monitors disk space and prevents over-allocation
Handles system signals for graceful shutdown
- Performance Characteristics:
Memory Usage: Scales with concurrent download count and video quality
CPU Usage: Minimal except during transcoding operations
Network Usage: Optimized with connection pooling and compression
Disk I/O: Efficient streaming writes to minimize disk thrashing
Response Time: Real-time progress updates every 100ms
- Example Usage:
Basic download execution:
>>> downloader = VideoDownloader() >>> downloader.download() # Output: Progress bars, status messages, completion notification
Error handling in scripts:
>>> import sys >>> try: ... downloader = VideoDownloader() ... downloader.download() ... print("Download completed successfully") ... except SystemExit as e: ... print(f"Download failed with exit code: {e.code}") ... sys.exit(e.code)
Integration with exception handling:
>>> try: ... downloader.download() ... except KeyboardInterrupt: ... print("Download cancelled by user") ... except Exception as e: ... print(f"Unexpected error: {e}") ... # Error details are already logged by the method
- Monitoring and Debugging:
The method provides extensive logging at multiple levels: - INFO: General progress and status information - WARNING: Non-critical issues and user interruptions - ERROR: Recoverable errors and retry attempts - CRITICAL: Unrecoverable errors requiring termination - DEBUG: Detailed internal state for troubleshooting
- Thread Safety:
This method is not thread-safe and should only be called once per VideoDownloader instance. The internal AsyncOrchestrator handles concurrency through async/await patterns within a single thread. For multi-threaded applications, create separate VideoDownloader instances for each thread.
- Note:
This method is designed to be called once per VideoDownloader instance and represents the complete lifecycle of a download session. Multiple calls may result in undefined behavior due to resource state management and configuration handling. Create a new VideoDownloader instance for each independent download session.
- See Also:
DIContainer.create_downloader_core: Creates configured download engine AsyncOrchestrator: Manages concurrent download operations and scheduling Messages.CLI: Internationalized user interface messages and error texts Config: Configuration options that affect download behavior LoggerFactory: Logging configuration and output management
- yt_dl_cli.main.main() None¶
Main entry point function for command-line execution.
This function serves as the primary entry point when the module is executed directly from the command line. It provides a clean interface for script execution and handles the complete lifecycle of a download session.
The function creates a VideoDownloader instance with default configuration (parsed from command-line arguments) and initiates the download process. It’s designed to be simple and straightforward for command-line usage.
- Process Flow:
Create VideoDownloader instance with default configuration
Parse command-line arguments automatically
Initialize logging and internationalization
Execute the download process
Handle completion or errors appropriately
- Returns:
- None: This function operates through side effects and process exit codes.
Success is indicated by normal completion, while errors result in non-zero exit codes.
- Raises:
- SystemExit: Raised by the VideoDownloader.download() method for critical
errors that require immediate termination. The exit code indicates the type of failure.
- Side Effects:
Parses command-line arguments from sys.argv
Creates VideoDownloader instance with parsed configuration
Executes complete download process with all associated side effects
May exit the process with non-zero code on failure
- Example:
Command-line usage:
$ python main.py –url “https://youtube.com/watch?v=example” $ python main.py –help $ python main.py –url “https://youtube.com/watch?v=example” –quality 720p
- Note:
This function is specifically designed for command-line execution. For programmatic usage, create VideoDownloader instances directly rather than calling this function.
- See Also:
VideoDownloader: Main orchestrator class for download operations parse_arguments: Command-line argument parsing implementation
Configuration¶
Configuration Management Module
This module provides configuration management functionality for the video downloader application. It defines the Config dataclass that holds all application settings including download paths, quality preferences, concurrency controls, and validation logic.
The module ensures configuration integrity through automatic validation and type conversion, providing a centralized way to manage application settings with proper error handling.
- Classes:
Config: Main configuration dataclass with validation
- class yt_dl_cli.config.config.Config(save_dir: ~pathlib.Path, max_workers: int, quality: str, audio_only: bool, urls: ~typing.List[str] = <factory>)¶
Bases:
objectConfiguration data class containing all application settings.
This class holds all the configuration parameters needed for the YouTube downloader application, including download paths, quality settings, and concurrency controls. It provides automatic validation of configuration values and type conversion where appropriate.
- Attributes:
- save_dir (Path): Directory where downloaded files will be saved.
Automatically converted to Path object if string is provided.
- max_workers (int): Maximum number of concurrent download threads.
Must be at least 1.
- quality (str): Video quality preference. Valid options are:
‘best’, ‘worst’, ‘720’, ‘480’, ‘360’.
audio_only (bool): Whether to download only audio (MP3) instead of video. urls (List[str]): List of URLs to download. Defaults to empty list.
- Raises:
ValueError: If max_workers is less than 1 or quality is not in valid options.
- Example:
>>> from pathlib import Path >>> config = Config( ... save_dir=Path("/downloads"), ... max_workers=4, ... quality="720", ... audio_only=False, ... urls=["https://example.com/video1", "https://example.com/video2"] ... )
- audio_only: bool¶
- max_workers: int¶
- quality: str¶
- save_dir: Path¶
- urls: List[str]¶
Core¶
YT-DL-CLI Video Downloader Core Module.
This module contains the core components responsible for the actual video downloading process. It provides a clean separation of concerns between video information extraction, download execution, and the orchestration of the complete download workflow.
The module is built around the principle of single responsibility, with each class handling a specific aspect of the download process. This design promotes testability, maintainability, and allows for easy extension and modification of individual components.
- Architecture Overview:
The module implements a layered architecture with clear separation between:
Information Layer (VideoInfoExtractor): - Extracts video metadata without downloading content - Validates video availability and accessibility - Retrieves video information for processing decisions
Execution Layer (DownloadExecutor): - Handles the actual download operations - Manages yt-dlp interactions and configurations - Provides error handling for download failures
Orchestration Layer (DownloaderCore): - Coordinates the complete download workflow - Integrates all components and dependencies - Manages resource lifecycle and cleanup - Handles file system operations and statistics
- Key Components:
VideoInfoExtractor: Metadata extraction and video validation
DownloadExecutor: Core download execution engine
DownloaderCore: Main orchestrator and workflow manager
- Design Patterns:
Strategy Pattern: Format selection through IFormatStrategy interface
Dependency Injection: All dependencies injected through constructor
Context Manager: Resource management with __enter__/__exit__ methods
Facade Pattern: DownloaderCore provides simplified interface to complex operations
Template Method: Standardized download workflow with extensible steps
- Error Handling Philosophy:
The module implements defensive programming practices: - All external API calls are wrapped in try-catch blocks - Errors are logged but don’t crash the application - Graceful degradation when individual downloads fail - Resource cleanup is guaranteed through context managers - Detailed error messages for troubleshooting and debugging
- Performance Considerations:
Efficient metadata extraction without unnecessary downloads
File existence checking to avoid redundant operations
Resource pooling and cleanup to prevent memory leaks
Asynchronous-friendly design for concurrent operations
Minimal I/O operations through smart caching strategies
- Integration Points:
The module integrates with several external systems: - yt-dlp: Primary download engine and video platform interface - File System: Through IFileChecker for file operations - Logging: Through ILogger for monitoring and debugging - Statistics: Through IStatsCollector for progress tracking - Configuration: Through Config for user preferences and settings - Internationalization: Through Messages for localized user feedback
- Usage Patterns:
The module is designed to be used in several contexts:
Single Download Operations: - Extract video information - Check file existence - Execute download if needed - Update statistics and logs
Batch Download Operation: - Process multiple URLs concurrently - Maintain statistics across operations - Handle individual failures gracefully
Integration with Async Systems: - Compatible with asyncio event loops - Non-blocking operations where possible - Resource cleanup compatible with async contexts
- Security Considerations:
Input validation for URLs and file paths
Safe filename sanitization to prevent directory traversal
Secure handling of temporary files and downloads
Validation of video information before processing
Protection against malicious URLs and content
- Thread Safety:
VideoInfoExtractor: Thread-safe, creates isolated yt-dlp instances
DownloadExecutor: Thread-safe, each operation uses separate context
DownloaderCore: Not thread-safe, designed for single-thread usage
Resource management: Requires careful coordination in multi-threaded environments
- Example Usage:
Basic usage with dependency injection:
>>> from yt_dl_cli.config.config import Config >>> from yt_dl_cli.utils.logger import LoggerFactory >>> >>> # Setup dependencies >>> config = Config(save_dir="/downloads", audio_only=False) >>> logger = LoggerFactory.get_logger("/downloads") >>> >>> # Create core components >>> info_extractor = VideoInfoExtractor(logger) >>> download_executor = DownloadExecutor(logger) >>> >>> # Create and use downloader core >>> with DownloaderCore(config, strategy, stats, logger, ... file_checker, info_extractor, download_executor) as core: ... core.download_single("https://youtube.com/watch?v=example")
- Dependencies:
- External Libraries:
yt-dlp: Video downloading and information extraction
typing: Type hints for better code documentation
- Internal Modules:
yt_dl_cli.i18n.messages: Internationalized user messages
yt_dl_cli.interfaces.interfaces: Core interface definitions
yt_dl_cli.interfaces.strategies: Format selection strategies
yt_dl_cli.utils.utils: Utility functions and helpers
yt_dl_cli.config.config: Configuration management
- Error Types:
The module handles several categories of errors: - Network errors: Connection timeouts, DNS failures - Platform errors: Video unavailable, private videos, geo-blocking - File system errors: Permission denied, disk full, invalid paths - Format errors: Unsupported formats, codec issues - Configuration errors: Invalid settings, missing dependencies
- Monitoring and Observability:
Detailed logging at multiple levels (DEBUG, INFO, WARNING, ERROR)
Statistics collection for success/failure rates
Progress tracking for individual downloads
Resource usage monitoring and cleanup verification
Performance metrics for optimization opportunities
- Testing Considerations:
The module is designed with testability in mind: - Dependency injection allows for easy mocking - Clear separation of concerns enables unit testing - Context managers ensure proper test cleanup - Error handling can be tested through exception simulation - Statistics tracking provides measurable test outcomes
- Version Compatibility:
Python 3.8+: Uses modern type hints and context managers
yt-dlp: Compatible with latest stable versions
Cross-platform: Works on Windows, macOS, and Linux
Unicode support: Handles international characters in titles and paths
- See Also:
yt_dl_cli.core.orchestration: Asynchronous orchestration layer
yt_dl_cli.interfaces.interfaces: Core interface definitions
yt_dl_cli.config.config: Configuration management documentation
yt_dl_cli.utils.utils: Utility functions and helpers
yt-dlp documentation: https://harley029.github.io/yt_dl_cli/
- class yt_dl_cli.core.core.DownloadExecutor(logger: ILogger)¶
Bases:
objectHandles the actual download execution using yt-dlp.
This class provides a clean interface to yt-dlp’s download functionality, focusing specifically on executing download operations with comprehensive error handling and logging. It serves as the execution engine for the download workflow, handling the actual file transfer and storage operations.
The class implements robust error handling to ensure that download failures are properly managed and don’t crash the application. It provides detailed logging for monitoring download progress and troubleshooting issues.
- Key Responsibilities:
Execute video/audio downloads using yt-dlp
Handle download-related errors and exceptions
Provide detailed logging for monitoring and debugging
Manage yt-dlp configuration and options
Support multiple output formats and quality settings
- Design Principles:
Single Responsibility: Only handles download execution
Defensive Programming: Comprehensive error handling
Logging Integration: Detailed progress and error reporting
Configuration Flexibility: Supports various yt-dlp options
- Error Categories:
The class handles several types of download errors: - Network errors: Connection issues, timeouts, bandwidth problems - Storage errors: Disk full, permission denied, invalid paths - Format errors: Unsupported formats, codec issues - Platform errors: Video removed, geo-blocked, private content
- Thread Safety:
This class is thread-safe as it creates isolated yt-dlp instances for each download operation and doesn’t maintain mutable state. Multiple threads can safely use the same DownloadExecutor instance.
- Performance Characteristics:
I/O intensive: Performance depends on network and disk speed
Memory efficient: Streaming downloads minimize memory usage
Resumable: Supports partial download resumption where possible
Concurrent friendly: Designed for use in concurrent environments
- Attributes:
- logger (ILogger): Logger instance for error reporting and progress tracking.
Used to record download attempts, progress updates, completion status, and detailed error information.
- Example:
Basic usage for single download:
>>> from yt_dl_cli.utils.logger import LoggerFactory >>> logger = LoggerFactory.get_logger("/downloads") >>> executor = DownloadExecutor(logger) >>> >>> # Configure download options >>> opts = { ... "format": "best[height<=720]", ... "outtmpl": "/downloads/%(title)s.%(ext)s", ... "writeinfojson": True ... } >>> >>> # Execute download >>> success = executor.execute_download("https://youtube.com/watch?v=example", opts) >>> if success: ... print("Download completed successfully") ... else: ... print("Download failed - check logs")
Batch download example:
>>> urls = ["https://youtube.com/watch?v=video1", "https://youtube.com/watch?v=video2"] >>> success_count = 0 >>> for url in urls: ... if executor.execute_download(url, opts): ... success_count += 1 >>> print(f"Successfully downloaded {success_count}/{len(urls)} videos")
- See Also:
yt_dlp.YoutubeDL: Primary download engine ILogger: Logging interface for progress tracking Messages.Executor: Localized error and status messages
- execute_download(url: str, opts: Dict[str, Any]) bool¶
Execute a download operation for a single URL.
This method performs the actual download using yt-dlp with the provided configuration options. It handles the complete download process including format selection, quality negotiation, file transfer, and storage operations. The method implements comprehensive error handling to ensure that failures are properly managed and logged.
The download process is designed to be robust and handle various error conditions gracefully, ensuring that individual download failures don’t crash the entire application. This makes it suitable for batch operations and concurrent download scenarios.
- Process Flow:
Create yt-dlp instance with provided options
Initiate download operation for the specified URL
Monitor download progress and handle any errors
Log success or failure with appropriate details
Return status indicator for calling code
- Args:
- url (str): Video URL to download. Should be a valid URL pointing to
a video on a platform supported by yt-dlp. The URL will be processed by yt-dlp’s URL recognition system to determine the appropriate extractor and download strategy.
- opts (Dict[str, Any]): yt-dlp configuration options for the download.
These options control all aspects of the download process including: - “format”: Quality and format selection - “outtmpl”: Output filename template - “writeinfojson”: Save metadata to JSON file - “writesubtitles”: Download subtitle files - “embedsubs”: Embed subtitles in video file - “extractaudio”: Extract audio only - “audioformat”: Audio format specification - “postprocessors”: Post-processing operations
- Returns:
- bool: True if the download completed successfully, False if it failed.
Success is determined by yt-dlp completing the download process without raising exceptions. The return value allows calling code to track success/failure rates and handle batch operations appropriately.
- Error Handling:
The method catches and handles several types of exceptions:
yt_dlp.DownloadError: Raised when yt-dlp encounters download-specific errors such as network issues, format unavailability, or storage problems. These are logged with detailed error information including the URL and specific error details.
Exception: Catches all other unexpected errors to prevent application crashes. This includes system-level errors, memory issues, and other unforeseen problems. All exceptions are logged with full details for debugging purposes.
- Side Effects:
Creates downloaded files in the specified output directory
May create temporary files during the download process
Updates file system with video/audio content and metadata
Generates log entries for monitoring and debugging
May modify network settings (proxy, user agent) during download
- Performance Considerations:
Network intensive: Download speed depends on connection bandwidth
Disk intensive: File writing performance affects overall speed
Memory efficient: Streaming downloads minimize memory usage
CPU usage: Varies with post-processing operations (transcoding, etc.)
Resumable: Supports partial download resumption where possible
- Example:
Basic download with minimal options:
>>> executor = DownloadExecutor(logger) >>> opts = {"format": "best", "outtmpl": "/downloads/%(title)s.%(ext)s"} >>> success = executor.execute_download("https://youtube.com/watch?v=example", opts)
High-quality video download with metadata:
>>> opts = { ... "format": "best[height<=1080]", ... "outtmpl": "/downloads/%(uploader)s - %(title)s.%(ext)s", ... "writeinfojson": True, ... "writesubtitles": True, ... "writeautomaticsub": True ... } >>> success = executor.execute_download(url, opts)
Audio-only download with format conversion:
>>> opts = { ... "format": "bestaudio/best", ... "outtmpl": "/music/%(title)s.%(ext)s", ... "extractaudio": True, ... "audioformat": "mp3", ... "audioquality": "192K" ... } >>> success = executor.execute_download(url, opts)
Error handling in batch operations:
>>> urls = ["https://youtube.com/watch?v=video1", "https://youtube.com/watch?v=video2"] >>> failed_urls = [] >>> for url in urls: ... if not executor.execute_download(url, opts): ... failed_urls.append(url) >>> print(f"Failed downloads: {len(failed_urls)}")
- Note:
This method is designed to be called multiple times with different URLs and options. Each call creates a fresh yt-dlp instance to ensure isolation and prevent state contamination between downloads.
All exceptions are caught and logged, ensuring that one failed download doesn’t crash the entire application. This makes the method safe for use in concurrent environments and batch processing scenarios.
- See Also:
yt_dlp.YoutubeDL: Primary download engine documentation yt_dlp.DownloadError: Download-related error handling Messages.Executor: Localized error and status message definitions Config: Configuration options that affect download behavior
- class yt_dl_cli.core.core.DownloaderCore(config: Config, strategy: IFormatStrategy, stats: IStatsCollector, logger: ILogger, file_checker: IFileChecker, info_extractor: VideoInfoExtractor, download_executor: DownloadExecutor)¶
Bases:
objectCore download logic coordinator that orchestrates the download process.
This class brings together all the components needed for downloading: configuration, format strategies, statistics, file checking, and the actual download execution. It handles the complete workflow for a single download operation.
- download_single(url: str) None¶
Download a single video from the provided URL.
This method orchestrates the complete download process for a single URL: 1. Extract video information to get title and check availability 2. Create sanitized filename and check if file already exists 3. Skip download if file exists, otherwise proceed with download 4. Update statistics based on the outcome
- Args:
url (str): Video URL to download
- Note:
This method handles all error conditions gracefully and updates statistics appropriately. It’s designed to be called concurrently for multiple URLs.
- register_resource(resource)¶
Register a resource for automatic cleanup.
- Args:
resource: Any object with a close() method that needs cleanup
- class yt_dl_cli.core.core.VideoInfoExtractor(logger: ILogger)¶
Bases:
objectHandles extraction of video metadata without downloading content.
This class provides a clean interface to yt-dlp’s information extraction capabilities, focusing specifically on retrieving video metadata without performing actual downloads. It serves as the first step in the download workflow, validating video availability and extracting necessary information for processing decisions.
The class implements robust error handling to ensure that metadata extraction failures don’t crash the application. It provides detailed logging for troubleshooting and monitoring purposes.
- Key Responsibilities:
Extract video metadata from URLs using yt-dlp
Validate video availability and accessibility
Handle platform-specific errors and limitations
Provide structured error reporting and logging
Support multiple video platforms through yt-dlp
- Design Principles:
Single Responsibility: Only handles information extraction
Defensive Programming: Extensive error handling and validation
Logging Integration: Comprehensive error reporting
Platform Agnostic: Works with any yt-dlp supported platform
- Error Handling:
The class handles several categories of errors: - Network errors: Connection timeouts, DNS failures - Platform errors: Video unavailable, private videos, geo-blocking - Parsing errors: Invalid URLs, malformed responses - Authentication errors: Age-restricted content, login required
- Thread Safety:
This class is thread-safe as it creates isolated yt-dlp instances for each operation and doesn’t maintain mutable state between calls. Multiple threads can safely use the same VideoInfoExtractor instance.
- Performance Characteristics:
Lightweight operations: Only extracts metadata, no downloads
Network dependent: Performance varies with connection speed
Caching friendly: Results can be cached by calling code
Memory efficient: Minimal memory footprint per operation
- Attributes:
- logger (ILogger): Logger instance for error reporting and debugging.
Used to record extraction attempts, failures, and detailed error information for troubleshooting.
- Example:
Basic usage for video information extraction:
>>> from yt_dl_cli.utils.logger import LoggerFactory >>> logger = LoggerFactory.get_logger("/tmp") >>> extractor = VideoInfoExtractor(logger) >>> >>> # Extract video information >>> opts = {"quiet": True, "no_warnings": True} >>> info = extractor.extract_info("https://youtube.com/watch?v=example", opts) >>> >>> if info: ... print(f"Title: {info.get('title')}") ... print(f"Duration: {info.get('duration')} seconds") ... print(f"Uploader: {info.get('uploader')}") ... else: ... print("Failed to extract video information")
Error handling example:
>>> info = extractor.extract_info("https://invalid-url", opts) >>> if info is None: ... print("Extraction failed - check logs for details")
- See Also:
yt_dlp.YoutubeDL: Primary extraction engine ILogger: Logging interface for error reporting Messages.Extractor: Localized error messages
- extract_info(url: str, opts: Dict[str, Any]) Any¶
Extract video information from a URL without downloading.
This method uses yt-dlp to retrieve comprehensive metadata about a video including title, duration, available formats, uploader information, and other platform-specific details. The extraction is performed without downloading any actual video content, making it efficient for validation and preprocessing tasks.
The method implements robust error handling to ensure that extraction failures are properly logged and don’t crash the application. It handles various error conditions including network failures, video unavailability, and platform-specific restrictions.
- Process Flow:
Create yt-dlp instance with provided options
Attempt to extract video information from URL
Validate that information was successfully retrieved
Handle any errors that occur during extraction
Log appropriate messages for monitoring and debugging
Return structured information or None on failure
- Args:
- url (str): Video URL to extract information from. Should be a valid
URL pointing to a video on a platform supported by yt-dlp. Examples include YouTube, Vimeo, Dailymotion, and hundreds of other video platforms.
- opts (Dict[str, Any]): yt-dlp configuration options for the extraction.
Common options include: - “quiet”: Suppress output messages - “no_warnings”: Disable warning messages - “extractaudio”: Audio extraction settings - “format”: Preferred format selection - “ignoreerrors”: Continue on errors
- Returns:
- Any: Video information dictionary from yt-dlp containing comprehensive
metadata about the video, or None if extraction failed. The dictionary typically includes: - “title”: Video title - “duration”: Video length in seconds - “uploader”: Channel or user name - “upload_date”: Publication date - “view_count”: Number of views - “formats”: Available quality/format options - “thumbnail”: Thumbnail image URL - “description”: Video description text - Platform-specific additional metadata
- Error Handling:
The method catches and handles several types of exceptions:
yt_dlp.DownloadError: Raised when yt-dlp encounters download-related errors such as network issues, authentication problems, or video unavailability. These are logged as extraction errors.
yt_dlp.utils.ExtractorError: Raised when yt-dlp’s extractor encounters platform-specific issues such as parsing errors, unsupported URLs, or API changes. These are logged with detailed error information.
Exception: Catches all other unexpected errors to prevent application crashes. These are logged as general extraction errors with full exception details for debugging.
- Performance Considerations:
Network dependent: Extraction time varies with connection speed
Lightweight operation: Only retrieves metadata, no file downloads
Caching opportunity: Results can be cached by calling code
Rate limiting: Respects platform rate limits automatically
- Example:
Basic information extraction:
>>> extractor = VideoInfoExtractor(logger) >>> opts = {"quiet": True, "no_warnings": True} >>> info = extractor.extract_info("https://youtube.com/watch?v=dQw4w9WgXcQ", opts) >>> >>> if info: ... print(f"Title: {info['title']}") ... print(f"Duration: {info['duration']} seconds") ... print(f"Uploader: {info['uploader']}") ... else: ... print("Failed to extract information")
Handling extraction failures:
>>> urls = ["https://youtube.com/watch?v=valid", "https://invalid-url"] >>> for url in urls: ... info = extractor.extract_info(url, opts) ... if info: ... print(f"Successfully extracted: {info['title']}") ... else: ... print(f"Failed to extract from: {url}")
Custom options for specific needs:
>>> opts = { ... "quiet": False, ... "no_warnings": False, ... "extract_flat": True, # For playlists ... "ignoreerrors": True ... } >>> info = extractor.extract_info(playlist_url, opts)
- Note:
This method is designed to be called multiple times with different URLs and options. Each call creates a fresh yt-dlp instance to ensure isolation and prevent state contamination between extractions.
Errors are logged but not raised, allowing the calling code to handle None return values gracefully and continue processing other URLs in batch operations.
- See Also:
yt_dlp.YoutubeDL: Primary extraction engine documentation yt_dlp.DownloadError: Download-related error handling yt_dlp.utils.ExtractorError: Extractor-specific error handling Messages.Extractor: Localized error message definitions
Orchestration¶
Asynchronous Download Orchestration Module
This module provides the main orchestration layer for managing concurrent video downloads. It contains the AsyncOrchestrator class for coordinating multiple downloads and the DIContainer class for dependency injection and component creation.
The module implements asynchronous processing using asyncio and ThreadPoolExecutor to efficiently handle multiple downloads while respecting concurrency limits and providing comprehensive statistics reporting.
- Classes:
AsyncOrchestrator: Main orchestrator for managing concurrent downloads DIContainer: Dependency injection container for component creation
- Key Features:
Asynchronous download coordination with configurable concurrency
Thread-based execution to avoid blocking the event loop
Comprehensive timing and statistics reporting
Dependency injection pattern for clean component composition
Proper resource management with context managers
- Dependencies:
asyncio: For asynchronous execution and event loop management
concurrent.futures: For thread pool execution
logging: For logger type hints and configuration
time: For performance timing measurements
typing: For type hints and annotations
Various yt_dl_cli modules: For core functionality and configuration
- class yt_dl_cli.core.orchestration.AsyncOrchestrator(core: DownloaderCore, config: Config)¶
Bases:
objectManages asynchronous execution of multiple downloads with concurrency control.
This class handles the coordination of multiple concurrent downloads using asyncio and ThreadPoolExecutor, providing efficient parallel processing while respecting the configured worker limits. It serves as the main orchestration layer for the download application.
The orchestrator manages the entire download lifecycle from initialization through completion, including timing measurements and final reporting.
- Attributes:
core (DownloaderCore): The core downloader instance used for each download config (Config): Configuration containing URLs and concurrency settings
- Example:
>>> import asyncio >>> from yt_dl_cli.config.config import Config >>> from pathlib import Path >>> >>> config = Config( ... save_dir=Path("/downloads"), ... max_workers=4, ... quality="720", ... audio_only=False, ... urls=["https://example.com/video1", "https://example.com/video2"] ... ) >>> core = DIContainer.create_downloader_core(config) >>> orchestrator = AsyncOrchestrator(core, config) >>> asyncio.run(orchestrator.run())
- async run() None¶
Execute all configured downloads asynchronously with timing and reporting.
This method orchestrates the complete download process: 1. Validates that there are URLs to download 2. Logs the start of operations with worker and URL counts 3. Creates a thread pool with the configured number of workers 4. Submits all download tasks to the thread pool using run_in_executor 5. Waits for all downloads to complete using asyncio.gather 6. Measures total elapsed time and generates final statistics report
The method uses asyncio.gather() to wait for all downloads to complete, ensuring that statistics are only reported after all work is done. Downloads run in threads to avoid blocking the asyncio event loop, since yt-dlp operations are CPU and I/O intensive.
- Raises:
- Exception: Any exception from individual downloads will be propagated
after other downloads complete (due to asyncio.gather behavior).
- Note:
If no URLs are configured, the method logs a warning and returns early without performing any downloads.
- Example:
>>> orchestrator = AsyncOrchestrator(core, config) >>> await orchestrator.run() # Logs: "Starting download of 5 URLs with 4 workers" # ... downloads execute concurrently ... # Logs: Final statistics report with timing information
- class yt_dl_cli.core.orchestration.DIContainer¶
Bases:
objectDependency injection container for creating fully configured downloader instances.
This class acts as a factory and dependency injection container, implementing the composition root pattern. It creates all the required components and wires them together to produce a ready-to-use downloader core with all dependencies properly injected.
The container centralizes dependency creation and management, making the system more testable and maintainable by removing direct dependencies between components.
- Static Methods:
create_downloader_core: Factory method for creating configured DownloaderCore instances
- Design Pattern:
This class implements the Dependency Injection Container pattern and Composition Root pattern, providing a single place where all object composition happens.
- static create_downloader_core(config: Config, logger: ILogger | None = None) DownloaderCore¶
Create a fully configured DownloaderCore with all dependencies injected.
This factory method creates and wires together all the components needed for a functioning downloader system. It handles the complete object graph construction, ensuring all components are properly configured and connected.
Components created and wired: - Logger: Configured for the specified save directory - Format strategy: Selected based on audio_only configuration - Statistics manager: For tracking download results - File system checker: For file existence validation - Video info extractor: For metadata retrieval - Download executor: For actual download operations - DownloaderCore: Main coordinator with all dependencies injected
- Args:
- config (Config): Application configuration to use for component setup.
Must contain valid save_dir, quality, audio_only settings.
- logger (Optional[logging.Logger], optional): Custom logger instance.
If None, creates a new logger using LoggerFactory. Defaults to None.
- Returns:
- DownloaderCore: Fully configured and ready-to-use downloader instance
with all dependencies properly injected and initialized.
- Example:
>>> from pathlib import Path >>> config = Config( ... save_dir=Path("/downloads"), ... max_workers=4, ... quality="720", ... audio_only=False ... ) >>> core = DIContainer.create_downloader_core(config) >>> # core is now ready to use with all dependencies configured
- Note:
This method implements the composition root pattern, centralizing all dependency creation and injection in one place. This makes the system more testable and maintainable by providing a single point of object graph construction.
Internationalization¶
Internationalization (i18n) utilities for application localization.
This module provides a simple interface for setting up GNU gettext-based internationalization in Python applications. It automatically detects the system locale, searches for translation files in common directory structures, and gracefully falls back to English when translations are unavailable.
The module is designed to work with standard GNU gettext .po/.mo file formats and follows common localization directory conventions used in many open-source projects.
- Note:
After calling setup_i18n(), the _() function becomes globally available for string translation throughout your application.
- yt_dl_cli.i18n.init.get_system_lang() str¶
Detect and return the system’s default language code.
This function attempts to determine the user’s preferred language by examining the system locale settings. It extracts the language portion from the full locale string and returns a standardized 2-character language code.
The function uses Python’s built-in locale module to query the system’s current locale configuration. If no locale is detected or an error occurs, it defaults to English (“en”).
- Returns:
- str: A 2-character language code (ISO 639-1 format).
Examples: “en” for English, “de” for German. Always returns “en” as fallback if system locale cannot be determined.
- Example:
>>> get_system_lang() 'en'
- Note:
The function truncates longer locale strings to just the language code. For example, “en_US.UTF-8” becomes “en”, “de_DE” becomes “de”.
- yt_dl_cli.i18n.init.setup_i18n(domain: str = 'messages', localedir: str | None = None, language: str | None = None) None¶
Set up internationalization (i18n) for the application.
This function configures the GNU gettext internationalization system by: 1. Detecting the system’s default locale 2. Loading the appropriate translation catalog 3. Installing the translation function globally
The function automatically falls back to English if the system locale cannot be determined or if translation files are not found.
- Args:
- domain (str, optional): The translation domain name, typically matching
the base name of .po/.mo files. Defaults to “messages”.
- localedir (str, optional): Directory path containing locale subdirectories
with translation files. Expected structure: localedir/ ├── en/ │ └── LC_MESSAGES/ │ ├── messages.po │ └── messages.mo └── … Defaults to “locales”.
- Returns:
None: This function has no return value but installs translation functions globally, making _() function available for string translation.
- Raises:
No exceptions are raised. If translation files are not found, the function gracefully falls back to installing a null translation that returns strings unchanged.
- Note:
After calling this function, the _() function becomes globally available for translating strings. The detected language is truncated to a 2-character language code (e.g., “en_US” becomes “en”) for compatibility with most translation file naming conventions.
Internationalization and message handling for user-facing text.
This module provides a comprehensive system for managing all user-facing messages in the application with support for internationalization (i18n). It implements lazy translation loading to ensure messages are translated at display time rather than at module import time, which is crucial for proper localization support.
The module is organized into logical message groups corresponding to different application components, making it easy to maintain and extend. Each message uses the LazyTranslation pattern to defer translation until the message is actually needed, ensuring the correct locale is used.
- Key Features:
Lazy translation loading for proper i18n support
Organized message groups by application component
Colorized console output with cross-platform support
Template-based messages with parameter substitution
Clean separation between message definitions and display logic
- Example:
Basic usage of messages and console output:
>>> from messages import Messages, console_printer >>> >>> # Display a configuration error >>> error_msg = Messages.Config.INVALID_WORKERS(workers=0) >>> console_printer.printout("red", error_msg) >>> >>> # Display download progress >>> start_msg = Messages.Core.START_DOWNLOAD(title="Example Video") >>> console_printer.printout("blue", start_msg)
- class yt_dl_cli.i18n.messages.LazyTranslation(template: str)¶
Bases:
objectDeferred translation wrapper for internationalization support.
This class implements lazy evaluation of translatable strings, ensuring that translation occurs at display time rather than at module load time. This is essential for proper internationalization because:
The user’s locale may not be determined at import time
The translation system may not be initialized when modules are loaded
The same message may need to be displayed in different locales during runtime
The class stores the message template and defers both translation and string formatting until the message is actually needed for display.
- Attributes:
template (str): The original message template with optional format placeholders.
- Example:
>>> msg = LazyTranslation("Hello {name}!") >>> # Translation and formatting happen when called: >>> translated_msg = msg(name="World") >>> print(translated_msg) # "Hello World!" (or translated equivalent)
- class yt_dl_cli.i18n.messages.Messages¶
Bases:
objectContainer for all user-facing messages in the application.
This class serves as a centralized registry for all translatable strings used throughout the application. Messages are organized into nested classes that correspond to different application components, making it easy to locate and maintain related messages.
Each message is wrapped in a LazyTranslation object to support proper internationalization. The hierarchical organization allows for:
Easy maintenance and updates of message text
Clear association between messages and application components
Efficient organization for translation tools and translators
Type-safe access to messages through the class hierarchy
The message groups are designed to match the application’s architecture, with separate groups for configuration, core functionality, CLI interface, statistics, and various processing components.
- Example:
>>> # Access configuration-related messages >>> error = Messages.Config.INVALID_WORKERS(workers=0) >>> >>> # Access download progress messages >>> start = Messages.Core.START_DOWNLOAD(title="My Video") >>> done = Messages.Core.DONE_DOWNLOAD(title="My Video")
- class CLI¶
Bases:
objectMessages used in the command-line interface.
This group contains messages specific to the command-line interface, including file handling errors, user interaction messages, and CLI-specific error conditions.
- CRITICAL_ERROR = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message displayed for critical errors that cause application termination.
- FILE_NOT_FOUND = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message displayed when a specified input file cannot be found.
- FILE_READ_ERROR = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message displayed when there’s an error reading an input file.
- USER_INTERRUPT = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message displayed when the user interrupts the download process (Ctrl+C).
- class Config¶
Bases:
objectMessages for configuration validation and errors.
This group contains all messages related to application configuration, including validation errors, invalid parameter notifications, and configuration-related warnings. These messages are typically displayed during application startup or when processing command-line arguments.
- INVALID_QUALITY = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message displayed when an unsupported quality setting is specified.
- INVALID_WORKERS = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message displayed when an invalid worker count is specified.
- class Core¶
Bases:
objectMessages used by the core downloader component.
This group contains messages related to the primary download functionality, including progress updates, completion notifications, and core operational messages. These are the most frequently displayed messages during normal application operation.
- DONE_DOWNLOAD = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message displayed when a download completes successfully.
- ERROR_RESOURCE_CLOSE = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message displayed when there’s an error during resource cleanup.
- SKIP_EXISTS = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message displayed when a download is skipped because the file already exists.
- START_DOWNLOAD = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message displayed when beginning a download operation.
- class Executor¶
Bases:
objectMessages used by the download executor component.
This group contains messages related to the actual download execution process, including error messages for failed downloads and executor-specific operational messages.
- ERROR_DOWNLOAD = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message displayed when a download operation fails.
- class Extractor¶
Bases:
objectMessages used by the video extractor component.
This group contains messages related to video information extraction, which occurs before the actual download process. These messages help users understand issues with URL processing and metadata extraction.
- ERROR_EXTRACT = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message displayed when video information extraction fails for a specific URL.
- ERROR_NO_INFO = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Generic message displayed when video information cannot be extracted.
- class Orchestrator¶
Bases:
objectMessages used by the async orchestrator.
This group contains messages related to the high-level coordination of download operations, including startup messages and orchestration status updates.
- NO_URLS = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message displayed when no URLs are provided for download.
- STARTING = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message displayed when beginning a batch download operation.
- class Stats¶
Bases:
objectMessages and formatting used for statistics reporting.
This group contains both translatable messages and formatting constants used to display download statistics and summary reports. The constants (HEADER, FOOTER) are not translatable as they are decorative elements.
- ELAPSED = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message showing total elapsed time for the operation.
- FAILED = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message showing number of failed downloads.
- FOOTER = '========================================'¶
Decorative footer line for statistics reports.
- HEADER = '========================================'¶
Decorative header line for statistics reports.
- PROCESSED = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message showing total number of items processed.
- SKIPPED = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message showing number of skipped downloads.
- SUCCESSFUL = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Message showing number of successful downloads.
- TITLE = <yt_dl_cli.i18n.messages.LazyTranslation object>¶
Title heading for the statistics summary.
Interfaces¶
Protocol interfaces for dependency injection and abstraction.
This module defines Protocol classes that establish contracts for various components used throughout the application. These protocols enable loose coupling, easier testing through mock implementations, and flexible architecture by defining clear interfaces without concrete implementations.
The protocols follow the Dependency Inversion Principle, allowing high-level modules to depend on abstractions rather than concrete implementations.
- class yt_dl_cli.interfaces.interfaces.IFileChecker(*args, **kwargs)¶
Bases:
ProtocolProtocol defining the interface for file system operations.
This abstraction allows for easy testing and alternative file system implementations while maintaining a consistent interface. It provides a minimal contract for file existence checking, which is commonly needed for validation, conditional processing, and avoiding duplicate operations.
Implementations can range from direct file system access to mock implementations for testing, remote file system adapters, or cached implementations that optimize repeated checks.
The protocol focuses on existence checking as this is often the primary file system query needed in download managers, file processors, and similar applications.
- exists(filepath: Path) bool¶
Check if a file exists at the given path.
This method should return True if a regular file exists at the specified path, and False otherwise. The behavior for directories, symbolic links, or other file system objects is implementation-defined but should be documented clearly.
Implementations should handle edge cases gracefully, such as: - Permission denied errors (typically return False) - Network timeouts for remote file systems - Invalid path formats - Non-existent parent directories
- Args:
- filepath (Path): A Path object representing the file location
to check. Should be an absolute or relative path that can be resolved by the underlying file system implementation.
- Returns:
- bool: True if the file exists and is accessible, False otherwise.
Does not distinguish between “file doesn’t exist” and “file exists but is not accessible”.
- class yt_dl_cli.interfaces.interfaces.ILogger(*args, **kwargs)¶
Bases:
ProtocolProtocol defining the interface for logger objects.
This protocol ensures that any logger implementation provides the necessary logging methods with consistent signatures for dependency injection. It abstracts the logging functionality to allow for different logging backends (standard library logging, custom loggers, or mock loggers for testing).
The protocol supports the standard logging levels and accepts flexible arguments to accommodate various logging patterns including string formatting, structured logging, and additional context via keyword arguments.
Methods should follow standard logging conventions where higher-level methods (critical, error) typically indicate more severe issues than lower-level ones (info, warning).
- critical(msg: Any, *args: Any, **kwargs: Any) None¶
Log a critical error message.
Used for very serious error conditions that may cause the program to terminate or indicate system-level failures that require immediate attention.
- Args:
- msg (Any): The critical error message to log. Can be a string
with format placeholders or any object with a string representation.
- *args (Any): Positional arguments for string formatting,
following Python’s % formatting convention.
- **kwargs (Any): Additional keyword arguments for detailed
error reporting, stack traces, or system context.
- Returns:
None
- error(msg: Any, *args: Any, **kwargs: Any) None¶
Log an error message.
Used for error conditions that prevented a specific operation from completing successfully but don’t necessarily terminate the entire program.
- Args:
- msg (Any): The error message to log. Can be a string with
format placeholders or any object with a string representation.
- *args (Any): Positional arguments for string formatting,
following Python’s % formatting convention.
- **kwargs (Any): Additional keyword arguments such as exc_info
for exception details or stack_info for call stack.
- Returns:
None
- info(msg: Any, *args: Any, **kwargs: Any) None¶
Log an informational message.
Used for general information about program execution flow, successful operations, or non-critical status updates.
- Args:
- msg (Any): The message to log. Can be a string with format
placeholders or any object with a string representation.
- *args (Any): Positional arguments for string formatting,
following Python’s % formatting convention.
- **kwargs (Any): Additional keyword arguments that may be
used by specific logger implementations (e.g., extra context, stack info, etc.).
- Returns:
None
- warning(msg: Any, *args: Any, **kwargs: Any) None¶
Log a warning message.
Used for potentially problematic situations that don’t prevent the program from continuing but may indicate issues that should be addressed or monitored.
- Args:
- msg (Any): The warning message to log. Can be a string with
format placeholders or any object with a string representation.
- *args (Any): Positional arguments for string formatting,
following Python’s % formatting convention.
- **kwargs (Any): Additional keyword arguments for logger-specific
features like stack traces or contextual information.
- Returns:
None
- class yt_dl_cli.interfaces.interfaces.IStatsCollector(*args, **kwargs)¶
Bases:
ProtocolProtocol defining the interface for statistics collection.
This protocol ensures consistent statistics tracking across different implementations, allowing for easy testing and alternative stat collectors. It provides a simple interface for recording different types of operations and generating summary reports.
Implementations should maintain internal counters for each type of recorded event and provide meaningful statistics through the report method. The protocol is designed to be thread-safe in implementations where concurrent access is expected.
The statistics collected can be used for monitoring application performance, generating user feedback, debugging issues, or creating audit trails.
- record_failure() None¶
Record a failed operation.
This method should be called whenever an operation fails due to errors, exceptions, or other issues that prevent successful completion. Implementations should increment their failure counter and may store additional context about the failure type or cause.
- Returns:
None
- record_skip() None¶
Record a skipped operation.
This method should be called when an operation is intentionally skipped rather than attempted. Common reasons include: file already exists, operation not needed due to current state, or user-defined filtering rules that exclude the operation.
Skipped operations are distinct from failures as they represent intentional non-execution rather than failed attempts.
- Returns:
None
- record_success() None¶
Record a successful operation.
This method should be called whenever an operation (such as a download, file processing, or data transformation) completes successfully without errors. Implementations should increment their success counter and may also record additional metadata like timestamps or operation details.
- Returns:
None
- report(logger: ILogger, elapsed: float) None¶
Generate and log a comprehensive summary report of collected statistics.
This method should compile all recorded statistics into a human-readable summary and output it using the provided logger. The report typically includes counts for each operation type, percentages, rates, and timing information.
- Args:
- logger (ILogger): The logger instance to use for outputting the
statistics report. Should typically use info level for normal reporting.
- elapsed (float): The total elapsed time in seconds for the
operations being reported. Used to calculate rates and performance metrics.
- Returns:
None
Format strategy implementations for media download configuration.
This module implements the Strategy design pattern to provide flexible format selection for media downloads. It abstracts the complexity of format specification into discrete strategy classes, allowing for easy extension and testing of different download configurations.
The module provides strategies for both video and audio-only downloads, with configurable quality settings and format preferences optimized for compatibility and user experience. The factory function enables clean separation between configuration parsing and strategy instantiation.
- Classes:
IFormatStrategy: Abstract base class defining the strategy interface VideoFormatStrategy: Concrete strategy for video downloads with quality control AudioFormatStrategy: Concrete strategy for audio-only downloads
- Functions:
get_strategy: Factory function for creating appropriate strategy instances
- Design Patterns:
Strategy Pattern: Encapsulates format selection algorithms
Factory Pattern: Provides centralized strategy instantiation
Abstract Base Class: Ensures consistent interface across strategies
- Example:
Basic usage with different configurations:
>>> from format_strategies import get_strategy >>> >>> # Audio download configuration >>> class AudioConfig: ... audio_only = True ... quality = "best" >>> >>> audio_strategy = get_strategy(AudioConfig()) >>> audio_opts = audio_strategy.get_opts() >>> print(audio_opts) {'format': 'bestaudio/best', 'extractaudio': True, 'audioformat': 'mp3'}
>>> # High-quality video configuration >>> class VideoConfig: ... audio_only = False ... quality = "1080" >>> >>> video_strategy = get_strategy(VideoConfig()) >>> video_opts = video_strategy.get_opts() >>> print(video_opts) {'format': 'best[height<=1080][ext=mp4]', 'merge_output_format': 'mp4'}
- Note:
The strategies are designed to work with yt-dlp library format specifications, but the pattern can be adapted for other download libraries by modifying the option dictionaries returned by get_opts() methods.
- class yt_dl_cli.interfaces.strategies.AudioFormatStrategy¶
Bases:
IFormatStrategyStrategy for downloading audio-only content in MP3 format.
This strategy extracts and converts audio streams to MP3 format, providing a consistent audio-only download experience regardless of the source video format.
- get_opts() Dict[str, Any]¶
Generate audio-only download options.
Configures the download to extract the best available audio stream and convert it to MP3 format for universal compatibility.
- Returns:
- Dict[str, Any]: Download options dictionary containing:
“format”: Audio format selector for best quality audio
“extractaudio”: Boolean flag to enable audio extraction
“audioformat”: Target audio format (MP3)
- Example:
>>> strategy = AudioFormatStrategy() >>> opts = strategy.get_opts() >>> print(opts) {'format': 'bestaudio/best', 'extractaudio': True, 'audioformat': 'mp3'}
- class yt_dl_cli.interfaces.strategies.IFormatStrategy¶
Bases:
ABCAbstract base class defining the interface for download format strategies.
This interface follows the Strategy pattern to encapsulate different format selection algorithms for media downloads. Each concrete strategy implements specific logic for choosing appropriate download formats and options.
- abstractmethod get_opts() Dict[str, Any]¶
Get download options dictionary for the specific format strategy.
- Returns:
Dict[str, Any]: A dictionary containing format-specific options that can be passed to a download library (e.g., yt-dlp).
- Raises:
NotImplementedError: If called on the abstract base class.
- class yt_dl_cli.interfaces.strategies.VideoFormatStrategy(quality: str)¶
Bases:
IFormatStrategyStrategy for downloading video content with configurable quality settings.
This strategy handles video downloads with quality preferences ranging from best available quality to specific resolution limits. It prioritizes MP4 format for better compatibility across devices and platforms.
- Attributes:
- quality (str): Quality setting that determines format selection.
Supported values: - “best”: Downloads highest quality video+audio - “worst”: Downloads lowest quality video - Numeric string (e.g., “720”): Downloads best video up to specified height
- get_opts() Dict[str, Any]¶
Generate video download options based on the quality setting.
Creates format selector strings optimized for video downloads: - For “best”: Selects best video+audio combination in MP4 - For “worst”: Selects lowest quality MP4 video - For numeric values: Selects best video up to specified height
- Returns:
- Dict[str, Any]: Download options dictionary containing:
“format”: Format selector string for video selection
“merge_output_format”: Output container format (MP4)
- Example:
>>> strategy = VideoFormatStrategy("720") >>> opts = strategy.get_opts() >>> print(opts) {'format': 'best[height<=720][ext=mp4]', 'merge_output_format': 'mp4'}
- yt_dl_cli.interfaces.strategies.get_strategy(config) IFormatStrategy¶
Factory function to create appropriate format strategy based on configuration.
This function implements the Factory pattern to instantiate the correct strategy based on the provided configuration object. It abstracts the strategy selection logic from the client code.
- Args:
- config: Configuration object that must have at least the following attributes:
audio_only (bool): Flag indicating if only audio should be downloaded
quality (str): Video quality setting (used only when audio_only is False)
- Returns:
IFormatStrategy: An instance of either AudioFormatStrategy or VideoFormatStrategy based on the configuration.
- Example:
>>> class Config: ... def __init__(self, audio_only=False, quality="best"): ... self.audio_only = audio_only ... self.quality = quality >>> >>> audio_config = Config(audio_only=True) >>> strategy = get_strategy(audio_config) >>> isinstance(strategy, AudioFormatStrategy) True >>> >>> video_config = Config(audio_only=False, quality="720") >>> strategy = get_strategy(video_config) >>> isinstance(strategy, VideoFormatStrategy) True
Scripts¶
Command Line Interface Entry Point Module for YT-DL-CLI Tool.
This module serves as the primary entry point for the video downloader command-line interface application. It provides a simple interface to initialize and execute the video downloading functionality through the main VideoDownloader class.
The module implements a clean separation of concerns by delegating the actual downloading logic to the main application module while providing a lightweight CLI wrapper for user interaction.
- Example:
This module is typically executed as a script or called from a package entry point:
$ python scripts/cli.py
Or when installed as a package:
$ yt-dl-cli
- yt_dl_cli.scripts.cli.main()¶
Main entry point function for the YT-DL-CLI application.
This function serves as the primary interface between the command-line environment and the core downloading functionality. It instantiates the VideoDownloader class and initiates the download process.
The function follows the single responsibility principle by focusing solely on application initialization and delegation to the core downloader logic. It handles the high-level orchestration while leaving specific download operations to the VideoDownloader class.
- Workflow:
Creates a new VideoDownloader instance
Calls the download method to start the download process
The VideoDownloader handles all user interaction, configuration, and actual downloading operations
- Returns:
- NoReturn: This function typically runs indefinitely or exits the
program upon completion, so it doesn’t return a value.
- Raises:
- SystemExit: May be raised by the VideoDownloader if a critical error
occurs or when the user requests to exit the application.
- KeyboardInterrupt: May be raised if the user interrupts the process
with Ctrl+C, though this should be handled by the VideoDownloader class.
- ImportError: May be raised if the main module or VideoDownloader
class cannot be imported due to missing dependencies or incorrect module structure.
- Note:
This function expects the VideoDownloader class to handle all user interaction, error handling, and graceful shutdown procedures. Any configuration or initialization parameters should be handled within the VideoDownloader class itself.
- See Also:
main.VideoDownloader: The core class that handles all download operations config.config: Configuration management for the application core.orchestration: Main orchestration logic for download workflows
Utils¶
Logging configuration factory module for the video downloader application.
This module provides a centralized logging configuration system that ensures consistent logging behavior across the entire application. It sets up both console and file-based logging with proper formatting and encoding support.
The module follows the factory pattern to create properly configured logger instances while preventing common logging pitfalls such as duplicate handlers and configuration conflicts.
Key Features: - Dual output logging (console + file) - Automatic log directory creation - UTF-8 encoding support for international characters - Singleton-like behavior to prevent handler duplication - Consistent timestamp and level formatting - Thread-safe logging operations
The logging system is designed to be robust and handle various edge cases including missing directories, encoding issues, and multiple initialization attempts.
- Example:
Basic usage of the logger factory:
>>> from pathlib import Path >>> logger = LoggerFactory.get_logger(Path("logs")) >>> logger.info("Download started") >>> logger.error("Failed to process video") >>> logger.warning("Quality not available, using fallback")
- Dependencies:
logging: Python standard library logging framework
pathlib: Cross-platform path handling
- class yt_dl_cli.utils.logger.ColorFormatter(fmt=None, datefmt=None, style='%', validate=True, *, defaults=None)¶
Bases:
FormatterCustom logging formatter that adds ANSI color codes to log messages.
This formatter extends the standard logging.Formatter to provide colored output for different log levels when displaying messages in the console. Colors help users quickly identify the severity of log messages.
The formatter applies different colors based on the log level: - DEBUG: Cyan - INFO: Green - WARNING: Yellow - ERROR: Red - CRITICAL: Red background
Color codes are only applied to console output and are automatically reset after each message to prevent color bleeding.
- Attributes:
Inherits all attributes from logging.Formatter
- Example:
>>> formatter = ColorFormatter("%(levelname)s: %(message)s") >>> handler = logging.StreamHandler() >>> handler.setFormatter(formatter) >>> logger.addHandler(handler) >>> logger.info("This will appear in green") >>> logger.error("This will appear in red")
- format(record)¶
Format a log record with appropriate color coding.
This method overrides the parent format method to add ANSI color codes before the formatted message and reset codes after it. The color is determined by the log level of the record.
- Args:
- record (logging.LogRecord): The log record to be formatted.
Contains information about the log event including level, message, timestamp, and other metadata.
- Returns:
- str: The formatted log message with ANSI color codes applied.
Format: “{color_code}{formatted_message}{reset_code}”
- Note:
Uses the parent class’s format method for the base formatting
Only adds color codes, doesn’t change the underlying format
Falls back to no color (RESET) if log level is not recognized
Color codes are compatible with most modern terminals
- class yt_dl_cli.utils.logger.LoggerFactory¶
Bases:
objectFactory class for creating and configuring logger instances.
This factory handles the setup of logging configuration including both console and file output, ensuring consistent logging behavior throughout the application. It implements a singleton-like pattern for the root logger configuration to prevent duplicate handlers and configuration conflicts.
The factory creates loggers with standardized formatting that includes timestamps, log levels, and message content. All log files are created with UTF-8 encoding to properly handle international characters in video titles and URLs.
- Design Pattern:
This class follows the Factory Method pattern, providing a centralized way to create configured logger instances while encapsulating the complexity of logging setup.
- Thread Safety:
The logging configuration is thread-safe as it relies on Python’s built-in logging module, which handles concurrent access internally.
- Attributes:
None (all methods are static)
- Example:
>>> # Create logger for downloads directory >>> logger = LoggerFactory.get_logger(Path("downloads")) >>> logger.info("Application started") >>> >>> # Logger can be reused across modules >>> same_logger = LoggerFactory.get_logger(Path("downloads")) >>> same_logger.warning("This uses the same configuration")
- static get_logger(save_dir: Path) Logger¶
Create and configure a logger instance with both console and file handlers.
This method sets up a comprehensive logging system that outputs to both the console (for immediate feedback) and a log file (for persistent record keeping). The method ensures the target directory exists and configures the root logger only once to prevent duplicate log entries.
The logging configuration includes: - DEBUG level logging (captures all log levels) - Timestamped log entries with ISO format - Standardized message format with level indicators - UTF-8 encoded file output for international character support - Colored console output for better readability - Plain text file output without color codes
- Args:
- save_dir (Path): Directory path where the log file will be created.
The directory will be created automatically if it doesn’t exist, including any parent directories. Must be a valid pathlib.Path object.
- Returns:
- logging.Logger: Configured logger instance named “video_dl_cli”
ready for immediate use. The logger is set to DEBUG level and will output to both console and the specified log file.
- Raises:
- OSError: May be raised if the save directory cannot be created
due to permission issues or invalid path specifications.
- PermissionError: Raised if the log file cannot be created or
written to due to insufficient permissions.
- Side Effects:
Creates the specified directory and any missing parent directories
Creates or appends to “download.log” file in the save directory
Clears existing handlers to prevent duplication
Configures both console and file handlers with appropriate formatters
- Example:
>>> from pathlib import Path >>> >>> # Basic usage >>> logger = LoggerFactory.get_logger(Path("./logs")) >>> logger.info("Starting download process") >>> logger.error("Failed to connect to server") >>> >>> # With nested directory creation >>> logger = LoggerFactory.get_logger(Path("./app/logs/downloads")) >>> logger.warning("Using fallback quality setting") >>> >>> # Debug level logging >>> logger.debug("Detailed debugging information")
- Log File Format:
The log file entries follow this format:
2024-01-15 14:30:25,123 [INFO] Download started for video XYZ 2024-01-15 14:30:26,456 [ERROR] Network timeout occurred 2024-01-15 14:30:27,789 [WARNING] Retrying download attempt
- Console Output:
Console output includes the same format but with color coding applied to help distinguish between different log levels.
- Note:
Clears existing handlers on each call to prevent duplication
Creates new handlers for both console and file output
Console handler uses ColorFormatter for colored output
File handler uses standard Formatter without colors
Log file is created with UTF-8 encoding for international support
The save directory is created with parents=True and exist_ok=True
Command line interface argument parsing module for the YouTube downloader CLI.
This module provides comprehensive command line argument parsing functionality for the async video downloader application. It handles URL input from both files and direct command line arguments, validates user input, and creates properly configured application settings.
Key Features: - Multiple URL input methods (file-based or direct CLI arguments) - Configurable download directory and quality settings - Concurrent download worker configuration - Audio-only download option - Robust error handling for file operations - Comment and empty line filtering in URL files
The module integrates with the application’s configuration system and internationalization framework to provide a seamless user experience.
- Example:
Basic usage from command line:
$ python -m yt_dl_cli -f urls.txt -d ./downloads -w 4 -q 720 $ python -m yt_dl_cli –urls “https://youtube.com/watch?v=xyz” -a $ python -m yt_dl_cli –file links.txt –workers 3 –quality best
- Dependencies:
argparse: Standard library argument parsing
pathlib: Cross-platform path handling
sys: System-specific parameters and functions
typing: Type hints for better code documentation
- yt_dl_cli.utils.parser.parse_arguments() Config¶
Parse command line arguments and create application configuration.
This function handles all command line argument parsing and validation, including reading URLs from files or command line arguments. It provides comprehensive error handling for file operations and processes URL lists by filtering out comments and empty lines.
The function creates an ArgumentParser instance, defines all supported command line options, parses the provided arguments, and then processes the URL input according to the specified method (file or direct URLs). Finally, it constructs and returns a fully populated Config object.
- Returns:
- Config: Fully populated configuration object containing all parsed
settings ready for use by the download application. The Config object includes validated paths, worker counts, quality settings, and a cleaned list of URLs.
- Raises:
- SystemExit: Raised by argparse when invalid arguments are provided
or when –help is requested. This is standard argparse behavior and should not be caught.
- Command Line Arguments:
- -f, –file (str): Path to file containing URLs, one per line.
Comments (lines starting with #) and empty lines are automatically ignored. Default: “links.txt”
- -d, –dir (str): Target directory for downloaded files. Directory
will be created if it doesn’t exist. Can be relative or absolute path. Default: “downloads”
- -w, –workers (int): Maximum number of concurrent download workers.
Higher values may improve download speed but consume more system resources. Default: 2
- -q, –quality (str): Preferred video quality for downloads.
Options: “best”, “worst”, “720”, “480”, “360” Default: “best”
- -a, –audio-only (flag): When present, downloads only the audio
track instead of video. Useful for music or podcast content.
- –urls (List[str]): Direct list of URLs to download. When provided,
this option overrides the –file option completely. Multiple URLs can be specified separated by spaces.
- File Format:
URL files should contain one URL per line. The following format is supported:
# This is a comment line (ignored) https://youtube.com/watch?v=video1 https://youtube.com/watch?v=video2
# Empty lines above are also ignored https://youtube.com/watch?v=video3
- Error Handling:
FileNotFoundError: When the specified URL file doesn’t exist, an error message is printed to stderr but execution continues with an empty URL list
Other file reading errors: Generic file reading errors are caught and reported with the specific error details
Invalid arguments: Handled by argparse with automatic help message display and program termination
- Example:
>>> # Parse arguments from command line >>> config = parse_arguments() >>> print(f"Will download {len(config.urls)} videos") >>> print(f"Save directory: {config.save_dir}") >>> print(f"Quality: {config.quality}") >>> print(f"Workers: {config.max_workers}")
- Note:
URLs starting with ‘#’ in files are treated as comments and ignored
Empty lines in URL files are automatically filtered out
Whitespace around URLs is automatically stripped
File reading errors are reported to stderr but don’t crash the program
The –urls option completely overrides file-based URL input
Path objects are used for cross-platform compatibility
Statistics Management Module
This module provides functionality for tracking and reporting download operation statistics. It includes the StatsManager class which maintains counters for various download outcomes and generates comprehensive reports with elapsed time information.
- Classes:
StatsManager: Main statistics tracking and reporting class
- Dependencies:
dataclasses: For creating the dataclass structure
typing: For type hints
yt_dl_cli.interfaces.interfaces: For logger interface
yt_dl_cli.i18n.messages: For internationalized messages
- class yt_dl_cli.utils.stats_manager.StatsManager(success: int = 0, failed: int = 0, skipped: int = 0)¶
Bases:
objectStatistics manager for tracking download operations and generating reports.
This class maintains counters for different types of download outcomes and provides methods for recording events and generating summary reports. It serves as a centralized point for collecting and reporting download session statistics including success rates, failures, and performance metrics.
- Attributes:
success (int): Count of successful downloads. Defaults to 0. failed (int): Count of failed downloads. Defaults to 0. skipped (int): Count of skipped downloads (files already exist). Defaults to 0.
- Example:
>>> stats = StatsManager() >>> stats.record_success() >>> stats.record_failure() >>> summary = stats.get_summary() >>> print(summary['total']) # Output: 2
- failed: int = 0¶
- get_summary() Dict[str, int]¶
Calculate and return a summary of all statistics.
Computes the total count by summing all individual counters and returns a comprehensive dictionary with all statistics.
- Returns:
- Dict[str, int]: Dictionary containing the following keys:
‘success’: Number of successful downloads
‘failed’: Number of failed downloads
‘skipped’: Number of skipped downloads
‘total’: Total number of processed items
- Example:
>>> stats = StatsManager() >>> stats.success = 5 >>> stats.failed = 2 >>> stats.skipped = 1 >>> summary = stats.get_summary() >>> summary {'success': 5, 'failed': 2, 'skipped': 1, 'total': 8}
- record_failure() None¶
Increment the failure counter by one.
This method should be called whenever a download operation fails due to any error condition.
- record_skip() None¶
Increment the skip counter by one.
This method should be called whenever a download operation is skipped, typically because the target file already exists.
- record_success() None¶
Increment the success counter by one.
This method should be called whenever a download operation completes successfully.
- report(logger: ILogger, elapsed: float) None¶
Generate and log a formatted summary report of download statistics.
Creates a detailed report showing the breakdown of download results and total elapsed time, formatted with visual separators for easy reading. The report includes header/footer formatting and uses internationalized messages for consistent presentation.
- Args:
- logger (ILogger): Logger instance to output the report. Must implement
the ILogger interface with an info() method.
- elapsed (float): Total elapsed time in seconds for the download session.
Should be a positive number representing the duration.
- Raises:
AttributeError: If the logger doesn’t implement the required interface.
- Example:
>>> import time >>> from unittest.mock import Mock >>> >>> logger = Mock() >>> stats = StatsManager() >>> stats.success = 10 >>> stats.failed = 2 >>> >>> start_time = time.time() >>> # ... perform downloads ... >>> elapsed_time = time.time() - start_time >>> >>> stats.report(logger, elapsed_time) This will log a formatted report with all statistics
- skipped: int = 0¶
- success: int = 0¶
File system utilities module for safe filename handling and file operations.
This module provides utilities for checking file existence and sanitizing filenames to ensure compatibility across different operating systems. The module includes two main classes:
FileSystemChecker: Wrapper for file system operations
FilenameSanitizer: Utility for sanitizing strings into safe filenames
The module is designed with testability in mind, providing abstractions that allow for easy mocking and alternative implementations.
- Example:
Basic usage of the file system utilities:
>>> from pathlib import Path >>> checker = FileSystemChecker() >>> sanitizer = FilenameSanitizer() >>> >>> # Check if a file exists >>> file_path = Path("example.txt") >>> if checker.exists(file_path): ... print("File exists") >>> >>> # Sanitize a filename >>> safe_name = sanitizer.sanitize("Video: Title with <special> chars!") >>> print(safe_name) # "Video_ Title with _special_ chars!"
- class yt_dl_cli.utils.utils.FileSystemChecker¶
Bases:
objectFile system operations wrapper for checking file existence.
This class provides an abstraction layer over file system operations, making the code more testable and allowing for alternative implementations. It can be easily mocked or extended for different file system backends.
- Attributes:
None
- Example:
>>> checker = FileSystemChecker() >>> file_path = Path("my_file.txt") >>> if checker.exists(file_path): ... print("File found!") ... else: ... print("File not found.")
- ensure_dir(path)¶
Create a directory and all necessary parent directories.
This method ensures that a directory exists at the specified path, creating it along with any missing parent directories if needed. If the directory already exists, the method completes successfully without raising an error.
This is equivalent to the Unix ‘mkdir -p’ command and is useful for preparing directory structures before file operations.
- Args:
- path (str or Path): Path where the directory should be created.
Can be either a string path or a pathlib.Path object. The path can be absolute or relative to the current working directory.
- Returns:
- None: This method doesn’t return a value. Success is indicated
by the absence of exceptions.
- Raises:
- OSError: Raised if directory creation fails due to:
Insufficient permissions
Path conflicts (e.g., a file exists with the same name)
Filesystem errors or limitations
- FileExistsError: Raised if the path exists but is not a directory
(e.g., it’s a regular file)
TypeError: If path cannot be converted to a Path object
- Example:
>>> checker = FileSystemChecker() >>> >>> # Create a simple directory >>> checker.ensure_dir("new_folder") >>> >>> # Create nested directories >>> checker.ensure_dir("path/to/deep/folder") >>> >>> # Works with Path objects >>> from pathlib import Path >>> output_dir = Path("./output/results/data") >>> checker.ensure_dir(output_dir) >>> >>> # Safe to call multiple times >>> checker.ensure_dir("existing_folder") # Won't raise error
- Note:
The method creates all missing parent directories automatically
If any part of the path already exists as a directory, it’s preserved
The method is idempotent: calling it multiple times is safe
File permissions for created directories follow system defaults
On Windows, this handles long path names appropriately
- exists(filepath: Path) bool¶
Check if a file exists at the specified path.
This method wraps the pathlib Path.exists() method to provide a consistent interface that can be easily mocked for testing or replaced with alternative implementations.
- Args:
- filepath (Path): Path object representing the file location
to check for existence
- Returns:
- bool: True if the file exists at the specified path,
False if the file does not exist or if there’s an error accessing the path
- Raises:
- OSError: May be raised if there are permission issues
accessing the file system (though this is rare for existence checks)
- Example:
>>> from pathlib import Path >>> checker = FileSystemChecker() >>> file_path = Path("/home/user/document.txt") >>> if checker.exists(file_path): ... print("File is available") ... else: ... print("File not found")
- is_dir(path)¶
Check if a path represents a directory (folder).
This method determines whether the specified path points to a directory rather than a regular file or other filesystem object. It provides a consistent interface that can be easily mocked for testing purposes.
The method handles both existing and non-existing paths gracefully: - For existing paths: returns True if it’s a directory, False otherwise - For non-existing paths: returns False
- Args:
- path (str or Path): Path to check. Can be either a string path
or a pathlib.Path object. The path can be absolute or relative to the current working directory.
- Returns:
- bool: True if the path exists and is a directory,
False if the path doesn’t exist, is a file, or is another type of filesystem object
- Raises:
- OSError: May be raised if there are permission issues
accessing the path or its parent directory
TypeError: If path cannot be converted to a Path object
- Example:
>>> checker = FileSystemChecker() >>> >>> # Check existing directory >>> if checker.is_dir("/home/user/documents"): ... print("It's a directory") >>> >>> # Check file (should return False) >>> if not checker.is_dir("/home/user/file.txt"): ... print("It's not a directory") >>> >>> # Works with Path objects too >>> from pathlib import Path >>> dir_path = Path("./my_folder") >>> if checker.is_dir(dir_path): ... print("Directory exists")
- class yt_dl_cli.utils.utils.FilenameSanitizer¶
Bases:
objectUtility class for sanitizing filenames to ensure file system compatibility.
This class handles the conversion of video titles and other strings into safe filenames that work across different operating systems including Windows, macOS, and Linux. It removes invalid characters and enforces length limits to prevent file system errors.
The sanitizer handles common problematic characters found in user-generated content such as video titles, avoiding issues with file creation and manipulation across different platforms.
- Attributes:
None (all methods are static)
- Example:
>>> sanitizer = FilenameSanitizer() >>> title = 'My Video: "The Best" <Part 1>' >>> safe_title = sanitizer.sanitize(title) >>> print(safe_title) # 'My Video_ _The Best_ _Part 1_'
- static sanitize(name: str, max_length: int = 100) str¶
Sanitize a string to make it safe for use as a filename.
Removes or replaces characters that are invalid in filenames on most operating systems, and truncates the result to a maximum length. This method handles the most common problematic characters that cause issues across Windows, macOS, and Linux file systems.
The following characters are replaced with underscores: - < > : “ / | ? *
- Args:
- name (str): Original string to sanitize. Can contain any
Unicode characters, though non-ASCII characters may cause issues on some older file systems.
- max_length (int, optional): Maximum length of resulting filename.
Defaults to 100 characters. Should be less than the file system’s limit (typically 255 characters).
- Returns:
- str: Sanitized filename safe for file system use. The result
will contain only characters that are safe across all major operating systems, with a length not exceeding the specified maximum.
- Raises:
TypeError: If name is not a string or max_length is not an integer ValueError: If max_length is less than 1
- Example:
>>> # Basic sanitization >>> FilenameSanitizer.sanitize('Video: "Title"') 'Video_ _Title_'
>>> # With custom length limit >>> long_title = "Very long video title that exceeds normal limits" >>> FilenameSanitizer.sanitize(long_title, max_length=20) 'Very long video titl'
>>> # Handling special characters >>> problematic = 'File<name>with:bad/chars\and|more?stuff*' >>> FilenameSanitizer.sanitize(problematic) 'File_name_with_bad_chars_and_more_stuff_'
- Note:
Invalid characters are replaced with underscores, not removed
Leading and trailing whitespace is stripped from the result
The method preserves the original string’s case
Empty strings or strings with only invalid characters will result in a string of underscores