Browse Source

[utils] Add `try_call`

pukkandan 2 years ago
parent
commit
c4f60dd7cd
5 changed files with 25 additions and 19 deletions
  1. 1 1
      CONTRIBUTING.md
  2. 3 3
      yt_dlp/downloader/http.py
  3. 6 5
      yt_dlp/extractor/mediasite.py
  4. 5 4
      yt_dlp/extractor/whowatch.py
  5. 10 6
      yt_dlp/utils.py

+ 1 - 1
CONTRIBUTING.md

@@ -643,7 +643,7 @@ Wrap all extracted numeric data into safe functions from [`yt_dlp/utils.py`](yt_
 
 Use `url_or_none` for safe URL processing.
 
-Use `try_get`, `dict_get` and `traverse_obj` for safe metadata extraction from parsed JSON.
+Use `traverse_obj` and `try_call` (superseeds `dict_get` and `try_get`) for safe metadata extraction from parsed JSON.
 
 Use `unified_strdate` for uniform `upload_date` or any `YYYYMMDD` meta field extraction, `unified_timestamp` for uniform `timestamp` extraction, `parse_filesize` for `filesize` extraction, `parse_count` for count meta fields extraction, `parse_resolution`, `parse_duration` for `duration` extraction, `parse_age_limit` for `age_limit` extraction. 
 

+ 3 - 3
yt_dlp/downloader/http.py

@@ -18,7 +18,7 @@ from ..utils import (
     parse_http_range,
     sanitized_Request,
     ThrottledDownload,
-    try_get,
+    try_call,
     write_xattr,
     XAttrMetadataError,
     XAttrUnavailableError,
@@ -120,12 +120,12 @@ class HttpFD(FileDownloader):
             else:
                 range_end = None
 
-            if try_get(None, lambda _: range_start > range_end):
+            if try_call(lambda: range_start > range_end):
                 ctx.resume_len = 0
                 ctx.open_mode = 'wb'
                 raise RetryDownload(Exception(f'Conflicting range. (start={range_start} > end={range_end})'))
 
-            if try_get(None, lambda _: range_end >= ctx.content_len):
+            if try_call(lambda: range_end >= ctx.content_len):
                 range_end = ctx.content_len - 1
 
             request = sanitized_Request(url, request_data, headers)

+ 6 - 5
yt_dlp/extractor/mediasite.py

@@ -14,6 +14,7 @@ from ..utils import (
     float_or_none,
     mimetype2ext,
     str_or_none,
+    try_call,
     try_get,
     unescapeHTML,
     unsmuggle_url,
@@ -145,11 +146,11 @@ class MediasiteIE(InfoExtractor):
                             'duration': slide['Time'] / 1000,
                         })
 
-            next_time = try_get(None, [
-                lambda _: Stream['Slides'][i + 1]['Time'],
-                lambda _: duration,
-                lambda _: slide['Time'],
-            ], expected_type=(int, float))
+            next_time = try_call(
+                lambda: Stream['Slides'][i + 1]['Time'],
+                lambda: duration,
+                lambda: slide['Time'],
+                expected_type=(int, float))
 
             fragments.append({
                 'path': fname_template.format(slide.get('Number', i + 1)),

+ 5 - 4
yt_dlp/extractor/whowatch.py

@@ -5,6 +5,7 @@ from .common import InfoExtractor
 from ..utils import (
     int_or_none,
     qualities,
+    try_call,
     try_get,
     ExtractorError,
 )
@@ -26,10 +27,10 @@ class WhoWatchIE(InfoExtractor):
         metadata = self._download_json('https://api.whowatch.tv/lives/%s' % video_id, video_id)
         live_data = self._download_json('https://api.whowatch.tv/lives/%s/play' % video_id, video_id)
 
-        title = try_get(None, (
-            lambda x: live_data['share_info']['live_title'][1:-1],
-            lambda x: metadata['live']['title'],
-        ), compat_str)
+        title = try_call(
+            lambda: live_data['share_info']['live_title'][1:-1],
+            lambda: metadata['live']['title'],
+            expected_type=str)
 
         hls_url = live_data.get('hls_url')
         if not hls_url:

+ 10 - 6
yt_dlp/utils.py

@@ -3096,15 +3096,19 @@ def dict_get(d, key_or_keys, default=None, skip_false_values=True):
     return d.get(key_or_keys, default)
 
 
-def try_get(src, getter, expected_type=None):
-    for get in variadic(getter):
+def try_call(*funcs, expected_type=None, args=[], kwargs={}):
+    for f in funcs:
         try:
-            v = get(src)
-        except (AttributeError, KeyError, TypeError, IndexError):
+            val = f(*args, **kwargs)
+        except (AttributeError, KeyError, TypeError, IndexError, ZeroDivisionError):
             pass
         else:
-            if expected_type is None or isinstance(v, expected_type):
-                return v
+            if expected_type is None or isinstance(val, expected_type):
+                return val
+
+
+def try_get(src, getter, expected_type=None):
+    return try_call(*variadic(getter), args=(src,), expected_type=expected_type)
 
 
 def filter_dict(dct, cndn=lambda _, v: v is not None):