11
11
import time
12
12
import uuid
13
13
from pathlib import Path
14
- from typing import Any , Callable , Dict , List , Optional
14
+ from typing import Any , Callable , Dict , List , Optional , Literal
15
15
16
16
17
17
logger = logging .getLogger (__name__ )
24
24
logger .warning ("yt-dlp not available. Install with: pip install yt-dlp" )
25
25
26
26
27
+ def make_ytdlp_wrapper (
28
+ default_output_dir : Optional [str ] = None ,
29
+ enable_logging : bool = True ,
30
+ default_quality : Literal ['best' , 'worst' ] = "best" ,
31
+ logger : logging .Logger = logging .getLogger (__name__ ),
32
+ ) -> 'YtDlpWrapper' :
33
+
34
+ resources = {
35
+ "default_output_dir" : default_output_dir ,
36
+ "enable_logging" : enable_logging ,
37
+ "default_quality" : default_quality ,
38
+ logger : logger
39
+ }
40
+
41
+ return YtDlpWrapper (** resources )
42
+
43
+ def type_name (obj : Any ) -> str :
44
+ return type (obj ).__name__
45
+
27
46
class YtDlpWrapper :
28
47
"""
29
48
YT-DLP Wrapper for Multi-Platform Media Downloads
@@ -69,6 +88,7 @@ class YtDlpWrapper:
69
88
default_quality (str): Default quality setting for downloads
70
89
downloads (Dict[str, Dict[str, Any]]): Registry tracking all download operations,
71
90
keyed by unique download IDs containing status, timing, and result information
91
+ logger (logging.Logger): Logger instance for outputting messages
72
92
73
93
Public Methods:
74
94
download_video(url, output_path=None, quality=None, **kwargs) -> Dict[str, Any]:
@@ -161,7 +181,9 @@ def progress_callback(download_id, progress_data):
161
181
def __init__ (self ,
162
182
default_output_dir : Optional [str ] = None ,
163
183
enable_logging : bool = True ,
164
- default_quality : str = "best" ):
184
+ default_quality : Literal ['best' , 'worst' ] = "best" ,
185
+ logger : logging .Logger = logging .getLogger (__name__ )
186
+ ):
165
187
"""
166
188
Initialize YT-DLP wrapper with configuration options and dependency validation.
167
189
@@ -182,8 +204,6 @@ def __init__(self,
182
204
not explicitly specified. Supported values include:
183
205
- 'best': Highest available quality
184
206
- 'worst': Lowest available quality
185
- - Resolution strings: '720p', '1080p', '480p'
186
- - Custom format selectors: 'best[height<=720]'
187
207
Defaults to "best".
188
208
189
209
Attributes initialized:
@@ -207,14 +227,14 @@ def __init__(self,
207
227
>>> wrapper = YtDlpWrapper(
208
228
... default_output_dir="/home/user/downloads",
209
229
... enable_logging=False,
210
- ... default_quality="720p "
230
+ ... default_quality="best "
211
231
... )
212
232
213
233
>>> # Production configuration
214
234
>>> wrapper = YtDlpWrapper(
215
235
... default_output_dir="/var/media/downloads",
216
236
... enable_logging=True,
217
- ... default_quality="best[height<=1080] "
237
+ ... default_quality="best"
218
238
... )
219
239
220
240
Notes:
@@ -223,14 +243,30 @@ def __init__(self,
223
243
- Download tracking dictionary starts empty and accumulates data over time
224
244
- All paths are converted to Path objects for cross-platform compatibility
225
245
"""
226
- self .default_output_dir = Path (default_output_dir or tempfile .gettempdir ())
227
- self .enable_logging = enable_logging
228
- self .default_quality = default_quality
229
- self .downloads = {} # Track active downloads
230
-
231
246
if not YTDLP_AVAILABLE :
232
247
raise ImportError ("yt-dlp is required but not installed. Install with: pip install yt-dlp" )
233
-
248
+
249
+ if default_output_dir is not None and not isinstance (default_output_dir , str ):
250
+ raise TypeError (f"default_output_dir must be a string, got { type_name (default_output_dir )} " )
251
+
252
+ if not isinstance (default_quality , str ):
253
+ raise TypeError (f"default_quality must be a string, got { type_name (default_quality )} " )
254
+
255
+ if default_quality not in ['best' , 'worst' ]:
256
+ raise ValueError (f"default_quality must be 'best' or 'worst', got { default_quality } " )
257
+
258
+ if not isinstance (enable_logging , bool ):
259
+ raise TypeError (f"enable_logging must be a boolean, got { type_name (enable_logging )} " )
260
+
261
+ if logger is not None and not isinstance (logger , logging .Logger ):
262
+ raise TypeError (f"logger must be a logging.Logger instance, got { type_name (logger )} " )
263
+
264
+ self .default_output_dir : Path = Path (default_output_dir or tempfile .gettempdir ())
265
+ self .enable_logging : bool = enable_logging
266
+ self .default_quality : Literal ['best' ,'worst' ] = default_quality
267
+ self .logger : logging .Logger = logger
268
+ self .downloads = {} # Track active downloads
269
+
234
270
async def download_video (self ,
235
271
url : str ,
236
272
output_path : Optional [str ] = None ,
0 commit comments