ytdl-sub 2025.12.31.post4__py3-none-any.whl → 2026.1.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ytdl_sub/__init__.py CHANGED
@@ -1 +1 @@
1
- __pypi_version__ = "2025.12.31.post4";__local_version__ = "2025.12.31+c46de04"
1
+ __pypi_version__ = "2026.01.06";__local_version__ = "2026.01.06+6b99c31"
@@ -238,20 +238,25 @@ class Overrides(UnstructuredDictFormatterValidator, Scriptable):
238
238
  def apply_overrides_formatter_to_native(
239
239
  self,
240
240
  formatter: OverridesStringFormatterValidator,
241
+ function_overrides: Optional[Dict[str, str]] = None,
241
242
  ) -> Any:
242
243
  """
243
244
  Parameters
244
245
  ----------
245
246
  formatter
246
247
  Overrides formatter to apply
248
+ function_overrides
249
+ Optional. Explicit values to override the overrides themselves and source variables
247
250
 
248
251
  Returns
249
252
  -------
250
253
  The native python form of the resolved variable
251
254
  """
252
- return self._apply_to_resolvable(
253
- formatter=formatter, entry=None, function_overrides=None
254
- ).native
255
+ return formatter.post_process_native(
256
+ self._apply_to_resolvable(
257
+ formatter=formatter, entry=None, function_overrides=function_overrides
258
+ ).native
259
+ )
255
260
 
256
261
  def evaluate_boolean(
257
262
  self, formatter: StringFormatterValidator, entry: Optional[Entry] = None
@@ -84,6 +84,9 @@ class VariableValidation:
84
84
  )
85
85
  resolved_subscription["download"] = []
86
86
  for url_output in raw_download_output["download"]:
87
+ if isinstance(url_output["url"], list):
88
+ url_output["url"] = [url for url in url_output["url"] if bool(url)]
89
+
87
90
  if url_output["url"]:
88
91
  resolved_subscription["download"].append(url_output)
89
92
 
@@ -52,12 +52,12 @@ class UrlDownloaderBasePluginExtension(SourcePluginExtension[MultiUrlValidator])
52
52
 
53
53
  if 0 <= input_url_idx < len(self.plugin_options.urls.list):
54
54
  validator = self.plugin_options.urls.list[input_url_idx]
55
- if self.overrides.apply_formatter(validator.url) == entry_input_url:
55
+ if entry_input_url in self.overrides.apply_overrides_formatter_to_native(validator.url):
56
56
  return validator
57
57
 
58
58
  # Match the first validator based on the URL, if one exists
59
59
  for validator in self.plugin_options.urls.list:
60
- if self.overrides.apply_formatter(validator.url) == entry_input_url:
60
+ if entry_input_url in self.overrides.apply_overrides_formatter_to_native(validator.url):
61
61
  return validator
62
62
 
63
63
  # Return the first validator if none exist
@@ -487,19 +487,27 @@ class MultiUrlDownloader(SourcePlugin[MultiUrlValidator]):
487
487
  # download the bottom-most urls first since they are top-priority
488
488
  for idx, url_validator in reversed(list(enumerate(self.collection.urls.list))):
489
489
  # URLs can be empty. If they are, then skip
490
- if not (url := self.overrides.apply_formatter(url_validator.url)):
490
+ if not (urls := self.overrides.apply_overrides_formatter_to_native(url_validator.url)):
491
491
  continue
492
492
 
493
- for entry in self._download_metadata(url=url, validator=url_validator):
494
- entry.initialize_script(self.overrides).add(
495
- {
496
- v.ytdl_sub_input_url: url,
497
- v.ytdl_sub_input_url_index: idx,
498
- v.ytdl_sub_input_url_count: len(self.collection.urls.list),
499
- }
500
- )
493
+ assert isinstance(urls, list)
494
+
495
+ for url in reversed(urls):
496
+ assert isinstance(url, str)
497
+
498
+ if not url:
499
+ continue
500
+
501
+ for entry in self._download_metadata(url=url, validator=url_validator):
502
+ entry.initialize_script(self.overrides).add(
503
+ {
504
+ v.ytdl_sub_input_url: url,
505
+ v.ytdl_sub_input_url_index: idx,
506
+ v.ytdl_sub_input_url_count: len(self.collection.urls.list),
507
+ }
508
+ )
501
509
 
502
- yield entry
510
+ yield entry
503
511
 
504
512
  def download(self, entry: Entry) -> Optional[Entry]:
505
513
  """
@@ -43,6 +43,19 @@ class UrlThumbnailListValidator(ListValidator[UrlThumbnailValidator]):
43
43
  _inner_list_type = UrlThumbnailValidator
44
44
 
45
45
 
46
+ class OverridesOneOrManyUrlValidator(OverridesStringFormatterValidator):
47
+ def post_process_native(self, resolved: Any) -> Any:
48
+ if isinstance(resolved, str):
49
+ return [resolved]
50
+ if isinstance(resolved, list):
51
+ for value in resolved:
52
+ if not isinstance(value, str):
53
+ raise self._validation_exception("Must be a string or an array of strings.")
54
+ return resolved
55
+
56
+ raise self._validation_exception("Must be a string or an array of strings.")
57
+
58
+
46
59
  class UrlValidator(StrictDictValidator):
47
60
  _required_keys = {"url"}
48
61
  _optional_keys = {
@@ -68,7 +81,7 @@ class UrlValidator(StrictDictValidator):
68
81
  super().__init__(name, value)
69
82
 
70
83
  # TODO: url validate using yt-dlp IE
71
- self._url = self._validate_key(key="url", validator=OverridesStringFormatterValidator)
84
+ self._url = self._validate_key(key="url", validator=OverridesOneOrManyUrlValidator)
72
85
  self._variables = self._validate_key_if_present(
73
86
  key="variables", validator=DictFormatterValidator, default={}
74
87
  )