[REFACTOR] Organize variable definitions (#860)

This commit is contained in:
Jesse Bannon 2023-12-29 14:39:19 -08:00 committed by GitHub
parent 189e897888
commit f2d55fdb23
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 1532 additions and 917 deletions

View file

@ -7,110 +7,163 @@ Entry Variables
channel
~~~~~~~
The channel name if it exists, otherwise returns the uploader.
:type: ``String``
:description:
The channel name if it exists, otherwise returns the uploader.
channel_id
~~~~~~~~~~
The channel id if it exists, otherwise returns the entry uploader ID.
:type: ``String``
:description:
The channel id if it exists, otherwise returns the entry uploader ID.
chapters
~~~~~~~~
Chapters if they exist
:type: ``Array``
:description:
Chapters if they exist
comments
~~~~~~~~
Comments if they are requested
:type: ``Array``
:description:
Comments if they are requested
creator
~~~~~~~
The creator name if it exists, otherwise returns the channel.
:type: ``String``
:description:
The creator name if it exists, otherwise returns the channel.
description
~~~~~~~~~~~
The description if it exists. Otherwise, returns an emtpy string.
:type: ``String``
:description:
The description if it exists. Otherwise, returns an emtpy string.
duration
~~~~~~~~
The duration of the entry in seconds
:type: ``Integer``
:description:
The duration of the entry in seconds if it exists. Defaults to zero otherwise.
epoch
~~~~~
The unix epoch of when the metadata was scraped by yt-dlp.
:type: ``Integer``
:description:
The unix epoch of when the metadata was scraped by yt-dlp.
epoch_date
~~~~~~~~~~
The epoch's date, in YYYYMMDD format.
:type: ``String``
:description:
The epoch's date, in YYYYMMDD format.
epoch_hour
~~~~~~~~~~
The epoch's hour
:type: ``String``
:description:
The epoch's hour
ext
~~~
The downloaded entry's file extension
:type: ``String``
:description:
The downloaded entry's file extension
extractor
~~~~~~~~~
The yt-dlp extractor name
:type: ``String``
:description:
The yt-dlp extractor name
extractor_key
~~~~~~~~~~~~~
The yt-dlp extractor key
:type: ``String``
:description:
The yt-dlp extractor key
ie_key
~~~~~~
The ie_key, used in legacy yt-dlp things as the 'info-extractor key'
:type: ``String``
:description:
The ie_key, used in legacy yt-dlp things as the 'info-extractor key'.
If it does not exist, return ``extractor_key``
info_json_ext
~~~~~~~~~~~~~
The "info.json" extension
:type: ``String``
:description:
The "info.json" extension
requested_subtitles
~~~~~~~~~~~~~~~~~~~
Subtitles if they are requested and exist
:type: ``Map``
:description:
Subtitles if they are requested and exist
sponsorblock_chapters
~~~~~~~~~~~~~~~~~~~~~
Sponsorblock Chapters if they are requested and exist
:type: ``Array``
:description:
Sponsorblock Chapters if they are requested and exist
thumbnail_ext
~~~~~~~~~~~~~
The download entry's thumbnail extension. Will always return 'jpg'. Until there is a
need to support other image types, we always convert to jpg.
:type: ``String``
:description:
The download entry's thumbnail extension. Will always return 'jpg'. Until there is a
need to support other image types, we always convert to jpg.
title
~~~~~
The title of the entry. If a title does not exist, returns its unique ID.
:type: ``String``
:description:
The title of the entry. If a title does not exist, returns its unique ID.
title_sanitized_plex
~~~~~~~~~~~~~~~~~~~~
The sanitized title with additional sanitizing for Plex. It replaces numbers with
fixed-width numbers so Plex does not recognize them as season or episode numbers.
:type: ``String``
:description:
The sanitized title with additional sanitizing for Plex. It replaces numbers with
fixed-width numbers so Plex does not recognize them as season or episode numbers.
uid
~~~
The entry's unique ID
:type: ``String``
:description:
The entry's unique ID
uid_sanitized_plex
~~~~~~~~~~~~~~~~~~
The sanitized uid with additional sanitizing for Plex. Replaces numbers with
fixed-width numbers so Plex does not recognize them as season or episode numbers.
:type: ``String``
:description:
The sanitized uid with additional sanitizing for Plex. Replaces numbers with
fixed-width numbers so Plex does not recognize them as season or episode numbers.
uploader
~~~~~~~~
The uploader if it exists, otherwise return the uploader ID.
:type: ``String``
:description:
The uploader if it exists, otherwise return the uploader ID.
uploader_id
~~~~~~~~~~~
The uploader id if it exists, otherwise return the unique ID.
:type: ``String``
:description:
The uploader id if it exists, otherwise return the unique ID.
uploader_url
~~~~~~~~~~~~
The uploader url if it exists, otherwise returns the webpage_url.
:type: ``String``
:description:
The uploader url if it exists, otherwise returns the webpage_url.
webpage_url
~~~~~~~~~~~
The url to the webpage.
:type: ``String``
:description:
The url to the webpage.
----------------------------------------------------------------------------------------------------
@ -119,19 +172,28 @@ Metadata Variables
entry_metadata
~~~~~~~~~~~~~~
The entry's info.json
:type: ``Map``
:description:
The entry's info.json
playlist_metadata
~~~~~~~~~~~~~~~~~
Metadata from the playlist (i.e. the parent metadata, like playlist -> entry)
:type: ``Map``
:description:
Metadata from the playlist (i.e. the parent metadata, like playlist -> entry)
sibling_metadata
~~~~~~~~~~~~~~~~
Metadata from any sibling entries that reside in the same playlist as this entry.
:type: ``Array``
:description:
Metadata from any sibling entries that reside in the same playlist as this entry.
source_metadata
~~~~~~~~~~~~~~~
Metadata from the source (i.e. the grandparent metadata, like channel -> playlist -> entry)
:type: ``Map``
:description:
Metadata from the source
(i.e. the grandparent metadata, like channel -> playlist -> entry)
----------------------------------------------------------------------------------------------------
@ -140,80 +202,114 @@ Playlist Variables
playlist_count
~~~~~~~~~~~~~~
Playlist count if it exists, otherwise returns ``1``.
:type: ``Integer``
:description:
Playlist count if it exists, otherwise returns ``1``.
Note that for channels/playlists, any change (i.e. adding or removing a video) will make
this value change. Use with caution.
Note that for channels/playlists, any change (i.e. adding or removing a video) will make
this value change. Use with caution.
playlist_description
~~~~~~~~~~~~~~~~~~~~
The playlist description if it exists, otherwise returns the entry's description.
:type: ``String``
:description:
The playlist description if it exists, otherwise returns the entry's description.
playlist_index
~~~~~~~~~~~~~~
Playlist index if it exists, otherwise returns ``1``.
:type: ``Integer``
:description:
Playlist index if it exists, otherwise returns ``1``.
Note that for channels/playlists, any change (i.e. adding or removing a video) will make
this value change. Use with caution.
Note that for channels/playlists, any change (i.e. adding or removing a video) will make
this value change. Use with caution.
playlist_index_padded
~~~~~~~~~~~~~~~~~~~~~
playlist_index padded two digits
:type: ``String``
:description:
playlist_index padded two digits
playlist_index_padded6
~~~~~~~~~~~~~~~~~~~~~~
playlist_index padded six digits.
:type: ``String``
:description:
playlist_index padded six digits.
playlist_index_reversed
~~~~~~~~~~~~~~~~~~~~~~~
Playlist index reversed via ``playlist_count - playlist_index + 1``
:type: ``Integer``
:description:
Playlist index reversed via ``playlist_count - playlist_index + 1``
playlist_index_reversed_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
playlist_index_reversed padded two digits
:type: ``String``
:description:
playlist_index_reversed padded two digits
playlist_index_reversed_padded6
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
playlist_index_reversed padded six digits.
:type: ``String``
:description:
playlist_index_reversed padded six digits.
playlist_max_upload_date
~~~~~~~~~~~~~~~~~~~~~~~~
Max upload_date for all entries in this entry's playlist if it exists, otherwise returns
``upload_date``
:type: ``String``
:description:
Max upload_date for all entries in this entry's playlist if it exists, otherwise returns
``upload_date``
playlist_max_upload_year
~~~~~~~~~~~~~~~~~~~~~~~~
Max upload_year for all entries in this entry's playlist if it exists, otherwise returns
``upload_year``
:type: ``Integer``
:description:
Max upload_year for all entries in this entry's playlist if it exists, otherwise returns
``upload_year``
playlist_max_upload_year_truncated
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The max playlist truncated upload year for all entries in this entry's playlist if it
exists, otherwise returns ``upload_year_truncated``.
:type: ``Integer``
:description:
The max playlist truncated upload year for all entries in this entry's playlist if it
exists, otherwise returns ``upload_year_truncated``.
playlist_title
~~~~~~~~~~~~~~
Name of its parent playlist/channel if it exists, otherwise returns its title.
:type: ``String``
:description:
Name of its parent playlist/channel if it exists, otherwise returns its title.
playlist_uid
~~~~~~~~~~~~
The playlist unique ID if it exists, otherwise return the entry unique ID.
:type: ``String``
:description:
The playlist unique ID if it exists, otherwise return the entry unique ID.
playlist_uploader
~~~~~~~~~~~~~~~~~
The playlist uploader if it exists, otherwise return the entry uploader.
:type: ``String``
:description:
The playlist uploader if it exists, otherwise return the entry uploader.
playlist_uploader_id
~~~~~~~~~~~~~~~~~~~~
The playlist uploader id if it exists, otherwise returns the entry uploader ID.
:type: ``String``
:description:
The playlist uploader id if it exists, otherwise returns the entry uploader ID.
playlist_uploader_url
~~~~~~~~~~~~~~~~~~~~~
The playlist uploader url if it exists, otherwise returns the playlist webpage_url.
:type: ``String``
:description:
The playlist uploader url if it exists, otherwise returns the playlist webpage_url.
playlist_webpage_url
~~~~~~~~~~~~~~~~~~~~
The playlist webpage url if it exists. Otherwise, returns the entry webpage url.
:type: ``String``
:description:
The playlist webpage url if it exists. Otherwise, returns the entry webpage url.
----------------------------------------------------------------------------------------------------
@ -222,75 +318,108 @@ Release Date Variables
release_date
~~~~~~~~~~~~
The entrys release date, in YYYYMMDD format. If not present, return the upload date.
:type: ``String``
:description:
The entrys release date, in YYYYMMDD format. If not present, return the upload date.
release_date_standardized
~~~~~~~~~~~~~~~~~~~~~~~~~
The release date formatted as YYYY-MM-DD
:type: ``String``
:description:
The uploaded date formatted as YYYY-MM-DD
release_day
~~~~~~~~~~~
The release day as an integer (no padding).
:type: ``Integer``
:description:
The upload day as an integer (no padding).
release_day_of_year
~~~~~~~~~~~~~~~~~~~
The day of the year, i.e. February 1st returns ``32``
:type: ``Integer``
:description:
The day of the year, i.e. February 1st returns ``32``
release_day_of_year_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~
The release day of year, but padded i.e. February 1st returns "032"
:type: ``String``
:description:
The upload day of year, but padded i.e. February 1st returns "032"
release_day_of_year_reversed
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The release day, but reversed using ``{total_days_in_year} + 1 - {release_day}``,
i.e. February 2nd would have release_day_of_year_reversed of ``365 + 1 - 32`` = ``334``
:type: ``Integer``
:description:
The upload day, but reversed using ``{total_days_in_year} + 1 - {release_day}``,
i.e. February 2nd would have release_day_of_year_reversed of ``365 + 1 - 32`` = ``334``
release_day_of_year_reversed_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The reversed release day of year, but padded i.e. December 31st returns "001"
:type: ``String``
:description:
The reversed upload day of year, but padded i.e. December 31st returns "001"
release_day_padded
~~~~~~~~~~~~~~~~~~
The entry's release day padded to two digits, i.e. the fifth returns "05"
:type: ``String``
:description:
The entry's upload day padded to two digits, i.e. the fifth returns "05"
release_day_reversed
~~~~~~~~~~~~~~~~~~~~
The release day, but reversed using ``{total_days_in_month} + 1 - {release_day}``,
i.e. August 8th would have release_day_reversed of ``31 + 1 - 8`` = ``24``
:type: ``Integer``
:description:
The upload day, but reversed using ``{total_days_in_month} + 1 - {release_day}``,
i.e. August 8th would have release_day_reversed of ``31 + 1 - 8`` = ``24``
release_day_reversed_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The reversed release day, but padded. i.e. August 30th returns "02".
:type: ``String``
:description:
The reversed upload day, but padded. i.e. August 30th returns "02".
release_month
~~~~~~~~~~~~~
The release month as an integer (no padding).
:type: ``Integer``
:description:
The upload month as an integer (no padding).
release_month_padded
~~~~~~~~~~~~~~~~~~~~
The entry's release month padded to two digits, i.e. March returns "03"
:type: ``String``
:description:
The entry's upload month padded to two digits, i.e. March returns "03"
release_month_reversed
~~~~~~~~~~~~~~~~~~~~~~
The release month, but reversed
using ``13 - {release_month}``, i.e. March returns ``10``
:type: ``Integer``
:description:
The upload month, but reversed using ``13 - {release_month}``, i.e. March returns ``10``
release_month_reversed_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The reversed release month, but padded. i.e. November returns "02"
:type: ``String``
:description:
The reversed upload month, but padded. i.e. November returns "02"
release_year
~~~~~~~~~~~~
The entry's release year
:type: ``Integer``
:description:
The entry's upload year
release_year_truncated
~~~~~~~~~~~~~~~~~~~~~~
The last two digits of the release year, i.e. 22 in 2022
:type: ``Integer``
:description:
The last two digits of the upload year, i.e. 22 in 2022
release_year_truncated_reversed
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The release year truncated, but reversed using ``100 - {release_year_truncated}``, i.e.
2022 returns ``100 - 22`` = ``78``
:type: ``Integer``
:description:
The upload year truncated, but reversed using ``100 - {release_year_truncated}``, i.e.
2022 returns ``100 - 22`` = ``78``
----------------------------------------------------------------------------------------------------
@ -299,47 +428,67 @@ Source Variables
source_count
~~~~~~~~~~~~
The source count if it exists, otherwise returns the playlist count.
:type: ``Integer``
:description:
The source count if it exists, otherwise returns ``1``.
source_description
~~~~~~~~~~~~~~~~~~
The source description if it exists, otherwise returns the playlist description.
:type: ``String``
:description:
The source description if it exists, otherwise returns the playlist description.
source_index
~~~~~~~~~~~~
Source index if it exists, otherwise returns ``1``.
:type: ``Integer``
:description:
Source index if it exists, otherwise returns ``1``.
It is recommended to not use this unless you know the source will never add new content
(it is easy for this value to change).
It is recommended to not use this unless you know the source will never add new content
(it is easy for this value to change).
source_index_padded
~~~~~~~~~~~~~~~~~~~
The source index, padded.
:type: ``String``
:description:
The source index, padded two digits.
source_title
~~~~~~~~~~~~
Name of the source (i.e. channel with multiple playlists) if it exists, otherwise
returns its playlist_title.
:type: ``String``
:description:
Name of the source (i.e. channel with multiple playlists) if it exists, otherwise
returns its playlist_title.
source_uid
~~~~~~~~~~
The source unique id if it exists, otherwise returns the playlist unique ID.
:type: ``String``
:description:
The source unique id if it exists, otherwise returns the playlist unique ID.
source_uploader
~~~~~~~~~~~~~~~
The source uploader if it exists, otherwise return the playlist_uploader
:type: ``String``
:description:
The source uploader if it exists, otherwise return the playlist_uploader
source_uploader_id
~~~~~~~~~~~~~~~~~~
The source uploader id if it exists, otherwise returns the playlist_uploader_id
:type: ``String``
:description:
The source uploader id if it exists, otherwise returns the playlist_uploader_id
source_uploader_url
~~~~~~~~~~~~~~~~~~~
The source uploader url if it exists, otherwise returns the source webpage_url.
:type: ``String``
:description:
The source uploader url if it exists, otherwise returns the source webpage_url.
source_webpage_url
~~~~~~~~~~~~~~~~~~
The source webpage url if it exists, otherwise returns the playlist webpage url.
:type: ``String``
:description:
The source webpage url if it exists, otherwise returns the playlist webpage url.
----------------------------------------------------------------------------------------------------
@ -348,74 +497,108 @@ Upload Date Variables
upload_date
~~~~~~~~~~~
The entrys uploaded date, in YYYYMMDD format. If not present, return todays date.
:type: ``String``
:description:
The entrys uploaded date, in YYYYMMDD format. If not present, return todays date.
upload_date_standardized
~~~~~~~~~~~~~~~~~~~~~~~~
The uploaded date formatted as YYYY-MM-DD
:type: ``String``
:description:
The uploaded date formatted as YYYY-MM-DD
upload_day
~~~~~~~~~~
The upload day as an integer (no padding).
:type: ``Integer``
:description:
The upload day as an integer (no padding).
upload_day_of_year
~~~~~~~~~~~~~~~~~~
The day of the year, i.e. February 1st returns ``32``
:type: ``Integer``
:description:
The day of the year, i.e. February 1st returns ``32``
upload_day_of_year_padded
~~~~~~~~~~~~~~~~~~~~~~~~~
The upload day of year, but padded i.e. February 1st returns "032"
:type: ``String``
:description:
The upload day of year, but padded i.e. February 1st returns "032"
upload_day_of_year_reversed
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The upload day, but reversed using ``{total_days_in_year} + 1 - {upload_day}``,
i.e. February 2nd would have upload_day_of_year_reversed of ``365 + 1 - 32`` = ``334``
:type: ``Integer``
:description:
The upload day, but reversed using ``{total_days_in_year} + 1 - {upload_day}``,
i.e. February 2nd would have upload_day_of_year_reversed of ``365 + 1 - 32`` = ``334``
upload_day_of_year_reversed_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The reversed upload day of year, but padded i.e. December 31st returns "001"
:type: ``String``
:description:
The reversed upload day of year, but padded i.e. December 31st returns "001"
upload_day_padded
~~~~~~~~~~~~~~~~~
The entry's upload day padded to two digits, i.e. the fifth returns "05"
:type: ``String``
:description:
The entry's upload day padded to two digits, i.e. the fifth returns "05"
upload_day_reversed
~~~~~~~~~~~~~~~~~~~
The upload day, but reversed using ``{total_days_in_month} + 1 - {upload_day}``,
i.e. August 8th would have upload_day_reversed of ``31 + 1 - 8`` = ``24``
:type: ``Integer``
:description:
The upload day, but reversed using ``{total_days_in_month} + 1 - {upload_day}``,
i.e. August 8th would have upload_day_reversed of ``31 + 1 - 8`` = ``24``
upload_day_reversed_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~
The reversed upload day, but padded. i.e. August 30th returns "02".
:type: ``String``
:description:
The reversed upload day, but padded. i.e. August 30th returns "02".
upload_month
~~~~~~~~~~~~
The upload month as an integer (no padding).
:type: ``Integer``
:description:
The upload month as an integer (no padding).
upload_month_padded
~~~~~~~~~~~~~~~~~~~
The entry's upload month padded to two digits, i.e. March returns "03"
:type: ``String``
:description:
The entry's upload month padded to two digits, i.e. March returns "03"
upload_month_reversed
~~~~~~~~~~~~~~~~~~~~~
The upload month, but reversed using ``13 - {upload_month}``, i.e. March returns ``10``
:type: ``Integer``
:description:
The upload month, but reversed using ``13 - {upload_month}``, i.e. March returns ``10``
upload_month_reversed_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The reversed upload month, but padded. i.e. November returns "02"
:type: ``String``
:description:
The reversed upload month, but padded. i.e. November returns "02"
upload_year
~~~~~~~~~~~
The entry's upload year
:type: ``Integer``
:description:
The entry's upload year
upload_year_truncated
~~~~~~~~~~~~~~~~~~~~~
The last two digits of the upload year, i.e. 22 in 2022
:type: ``Integer``
:description:
The last two digits of the upload year, i.e. 22 in 2022
upload_year_truncated_reversed
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The upload year truncated, but reversed using ``100 - {upload_year_truncated}``, i.e.
2022 returns ``100 - 22`` = ``78``
:type: ``Integer``
:description:
The upload year truncated, but reversed using ``100 - {upload_year_truncated}``, i.e.
2022 returns ``100 - 22`` = ``78``
----------------------------------------------------------------------------------------------------
@ -424,29 +607,43 @@ Ytdl-Sub Variables
download_index
~~~~~~~~~~~~~~
The i'th entry downloaded. NOTE that this is fetched dynamically from the download
archive.
:type: ``Integer``
:description:
The i'th entry downloaded. NOTE that this is fetched dynamically from the download
archive.
download_index_padded6
~~~~~~~~~~~~~~~~~~~~~~
The download_index padded six digits
:type: ``String``
:description:
The download_index padded six digits
upload_date_index
~~~~~~~~~~~~~~~~~
The i'th entry downloaded with this upload date.
:type: ``Integer``
:description:
The i'th entry downloaded with this upload date.
upload_date_index_padded
~~~~~~~~~~~~~~~~~~~~~~~~
The upload_date_index padded two digits
:type: ``String``
:description:
The upload_date_index padded two digits
upload_date_index_reversed
~~~~~~~~~~~~~~~~~~~~~~~~~~
100 - upload_date_index
:type: ``Integer``
:description:
100 - upload_date_index
upload_date_index_reversed_padded
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The upload_date_index padded two digits
:type: ``String``
:description:
The upload_date_index padded two digits
ytdl_sub_input_url
~~~~~~~~~~~~~~~~~~
The input URL used in ytdl-sub to create this entry.
:type: ``String``
:description:
The input URL used in ytdl-sub to create this entry.

View file

@ -603,7 +603,7 @@ Takes a date in the form of YYYYMMDD and returns a Map containing:
- year (Integer)
- month (Integer)
- day (Integer)
- year_truncated (String, YY from YY[YY])
- year_truncated (Integer, YY from YY[YY])
- month_padded (String)
- day_padded (String)
- year_truncated_reversed (Integer, 100 - year_truncated)

View file

@ -13,7 +13,7 @@ from ytdl_sub.config.plugin.preset_plugins import PresetPlugins
from ytdl_sub.config.preset_options import OutputOptions
from ytdl_sub.config.validators.options import OptionsValidator
from ytdl_sub.downloaders.url.validators import MultiUrlValidator
from ytdl_sub.entries.script.variable_scripts import VARIABLE_SCRIPTS
from ytdl_sub.entries.script.variable_definitions import VARIABLE_SCRIPTS
from ytdl_sub.script.script import Script
from ytdl_sub.validators.string_formatter_validators import validate_formatters

View file

@ -11,10 +11,9 @@ from ytdl_sub.config.validators.options import OptionsDictValidator
from ytdl_sub.downloaders.source_plugin import SourcePlugin
from ytdl_sub.downloaders.ytdl_options_builder import YTDLOptionsBuilder
from ytdl_sub.entries.entry import Entry
from ytdl_sub.entries.script.variable_definitions import VARIABLE_SCRIPTS
from ytdl_sub.entries.script.variable_definitions import VARIABLES
from ytdl_sub.entries.script.variable_definitions import VariableDefinitions
from ytdl_sub.entries.script.variable_scripts import DOWNLOADER_INJECTED_VARIABLES
from ytdl_sub.entries.script.variable_scripts import VARIABLE_SCRIPTS
from ytdl_sub.utils.exceptions import ValidationException
from ytdl_sub.utils.file_handler import FileHandler
from ytdl_sub.utils.file_handler import get_file_extension
@ -114,7 +113,7 @@ class InfoJsonDownloader(SourcePlugin[InfoJsonDownloaderOptions]):
inj.variable_name,
VARIABLE_SCRIPTS[inj.variable_name],
)
for inj in DOWNLOADER_INJECTED_VARIABLES
for inj in v.injected_variables()
}
)
entries.append(entry)

View file

@ -12,8 +12,10 @@ from typing import final
from ytdl_sub.entries.base_entry import BaseEntry
from ytdl_sub.entries.script.variable_definitions import VARIABLES
from ytdl_sub.entries.script.variable_definitions import Variable
from ytdl_sub.entries.script.variable_definitions import VariableDefinitions
from ytdl_sub.entries.script.variable_types import ArrayVariable
from ytdl_sub.entries.script.variable_types import StringVariable
from ytdl_sub.entries.script.variable_types import Variable
from ytdl_sub.script.utils.exceptions import ScriptVariableNotResolved
from ytdl_sub.utils.script import ScriptUtils
from ytdl_sub.utils.scriptable import Scriptable
@ -23,8 +25,12 @@ from ytdl_sub.validators.audo_codec_validator import VIDEO_CODEC_EXTS
v: VariableDefinitions = VARIABLES
_YTDL_SUB_ENTRY_VARIABLES_KWARG_KEY: str = "ytdl_sub_entry_variables"
ytdl_sub_chapters_from_comments = Variable("ytdl_sub_chapters_from_comments")
ytdl_sub_split_by_chapters_parent_uid = Variable("ytdl_sub_split_by_chapters_parent_uid")
ytdl_sub_chapters_from_comments = ArrayVariable(
"ytdl_sub_chapters_from_comments", definition="{ [] }"
)
ytdl_sub_split_by_chapters_parent_uid = StringVariable(
"ytdl_sub_split_by_chapters_parent_uid", definition="{ %string('') }"
)
TypeT = TypeVar("TypeT")

View file

@ -3,15 +3,14 @@ from typing import Any
from typing import Dict
from typing import List
from typing import Optional
from typing import Set
from ytdl_sub.entries.base_entry import BaseEntry
from ytdl_sub.entries.base_entry import TBaseEntry
from ytdl_sub.entries.entry import Entry
from ytdl_sub.entries.script.variable_definitions import VARIABLES
from ytdl_sub.entries.script.variable_definitions import MetadataVariable
from ytdl_sub.entries.script.variable_definitions import VariableDefinitions
from ytdl_sub.entries.script.variable_scripts import ENTRY_DEFAULT_VARIABLES
from ytdl_sub.entries.script.variable_scripts import ENTRY_REQUIRED_VARIABLES
from ytdl_sub.entries.script.variable_types import MetadataVariable
v: VariableDefinitions = VARIABLES
@ -53,8 +52,8 @@ class EntryParent(BaseEntry):
def _sibling_entry_metadata(self) -> List[Dict[str, Any]]:
sibling_entry_metadata: List[Dict[str, Any]] = []
variable_filter: List[MetadataVariable] = list(ENTRY_REQUIRED_VARIABLES.keys()) + list(
ENTRY_DEFAULT_VARIABLES.keys()
variable_filter: Set[MetadataVariable] = (
v.required_entry_variables() | v.default_entry_variables()
)
for entry in self.entry_children():
sibling_entry_metadata.append(

View file

@ -101,7 +101,7 @@ class CustomFunctions:
- year (Integer)
- month (Integer)
- day (Integer)
- year_truncated (String, YY from YY[YY])
- year_truncated (Integer, YY from YY[YY])
- month_padded (String)
- day_padded (String)
- year_truncated_reversed (Integer, 100 - year_truncated)
@ -149,7 +149,7 @@ class CustomFunctions:
String("year"): Integer(year),
String("month"): Integer(month),
String("day"): Integer(day),
String("year_truncated"): String(year_truncated),
String("year_truncated"): Integer(year_truncated),
String("month_padded"): String(month_padded),
String("day_padded"): String(day_padded),
String("year_truncated_reversed"): Integer(100 - year_truncated),

File diff suppressed because it is too large Load diff

View file

@ -1,296 +0,0 @@
from typing import Dict
from typing import List
from typing import Optional
from typing import Set
import mergedeep
from ytdl_sub.entries.script.custom_functions import CustomFunctions
from ytdl_sub.entries.script.variable_definitions import VARIABLES
from ytdl_sub.entries.script.variable_definitions import Metadata
from ytdl_sub.entries.script.variable_definitions import MetadataVariable
from ytdl_sub.entries.script.variable_definitions import Variable
from ytdl_sub.entries.script.variable_definitions import VariableDefinitions
###############################################################################################
# Helpers
v: VariableDefinitions = VARIABLES
def _pad_int(key: Variable, pad: int) -> str:
return f"{{%pad_zero({key.variable_name}, {pad})}}"
def _sanitized_plex(key: Variable) -> str:
return f"{{%sanitize_plex_episode({key.variable_name})}}"
def _date_metadata(date_key: Variable, metadata_key: str) -> str:
return f"{{%map_get(%to_date_metadata({date_key.variable_name}), '{metadata_key}')}}"
###############################################################################################
# Metadata Getters
def _get(
cast: str,
metadata: Metadata,
key: MetadataVariable,
default: Optional[Variable | str | int | Dict | List],
) -> str:
if default is None:
# TODO: assert with good error message if key DNE
out = f"%map_get({metadata.variable_name}, '{key.metadata_key}')"
elif isinstance(default, Variable):
args = f"{metadata.variable_name}, '{key.metadata_key}', {default.variable_name}"
out = f"%map_get_non_empty({args})"
elif isinstance(default, str):
out = f"%map_get_non_empty({metadata.variable_name}, '{key.metadata_key}', '{default}')"
elif isinstance(default, dict):
out = f"%map_get_non_empty({metadata.variable_name}, '{key.metadata_key}', {{}})"
elif isinstance(default, list):
out = f"%map_get_non_empty({metadata.variable_name}, '{key.metadata_key}', [])"
else:
out = f"%map_get_non_empty({metadata.variable_name}, '{key.metadata_key}', {default})"
return f"{{ %legacy_bracket_safety(%{cast}({out})) }}"
###############################################################################################
# Entry Getters
def _entry_get_str(key: MetadataVariable, default: Optional[Variable | str] = None) -> str:
return _get("string", metadata=v.entry_metadata, key=key, default=default)
def _entry_get_int(key: MetadataVariable, default: Optional[Variable | int] = None) -> str:
return _get("int", metadata=v.entry_metadata, key=key, default=default)
def _entry_get_map(key: MetadataVariable, default: Optional[Variable | Dict] = None):
return _get("map", metadata=v.entry_metadata, key=key, default=default)
def _entry_get_array(key: MetadataVariable, default: Optional[Variable | List] = None):
return _get("array", metadata=v.entry_metadata, key=key, default=default)
###############################################################################################
# Playlist Getters
def _playlist_get_str(key: MetadataVariable, default: Optional[Variable | str] = None) -> str:
return _get("string", metadata=v.playlist_metadata, key=key, default=default)
def _playlist_get_int(key: MetadataVariable, default: Optional[Variable | int] = None) -> str:
return _get("int", metadata=v.playlist_metadata, key=key, default=default)
###############################################################################################
# Source Getters
def _source_get_str(key: MetadataVariable, default: Optional[Variable | str] = None) -> str:
return _get("string", metadata=v.source_metadata, key=key, default=default)
###############################################################################################
# Scripts
ENTRY_EMPTY_METADATA: Dict[Variable, str] = {v.entry_metadata: "{ {} }"}
ENTRY_HARDCODED_VARIABLES: Dict[Variable, str] = {
v.info_json_ext: "info.json",
v.thumbnail_ext: "jpg",
}
ENTRY_RELATIVE_VARIABLES: Dict[MetadataVariable, str] = {
v.playlist_metadata: _entry_get_map(v.playlist_metadata, {}),
v.source_metadata: _entry_get_map(v.source_metadata, {}),
v.sibling_metadata: _entry_get_array(v.sibling_metadata, []),
}
ENTRY_REQUIRED_VARIABLES: Dict[MetadataVariable, str] = {
v.uid: _entry_get_str(v.uid),
v.extractor_key: _entry_get_str(v.extractor_key),
v.epoch: _entry_get_int(v.epoch),
v.webpage_url: _entry_get_str(v.webpage_url),
v.ext: _entry_get_str(v.ext),
}
ENTRY_DEFAULT_VARIABLES: Dict[MetadataVariable, str] = {
v.title: _entry_get_str(v.title, v.uid),
v.extractor: _entry_get_str(v.extractor, v.extractor_key),
v.description: _entry_get_str(v.description, ""),
v.ie_key: _entry_get_str(v.ie_key, v.extractor_key),
v.uploader_id: _entry_get_str(v.uploader_id, v.uid),
v.uploader: _entry_get_str(v.uploader, v.uploader_id),
v.uploader_url: _entry_get_str(v.uploader_url, v.webpage_url),
v.upload_date: _entry_get_str(v.upload_date, v.epoch_date),
v.release_date: _entry_get_str(v.release_date, v.upload_date),
v.channel: _entry_get_str(v.channel, v.uploader),
v.creator: _entry_get_str(v.creator, v.channel),
v.channel_id: _entry_get_str(v.channel_id, v.uploader_id),
v.duration: _entry_get_int(v.duration, 0),
v.playlist_index: _entry_get_int(v.playlist_index, 1),
v.playlist_count: _entry_get_int(v.playlist_count, 1),
v.playlist_uid: _entry_get_str(v.playlist_uid, v.uid),
v.playlist_title: _entry_get_str(v.playlist_title, v.title),
v.playlist_uploader_id: _entry_get_str(v.playlist_uploader_id, v.uploader_id),
}
# MARK AS UNRESOLVABLE UNTIL THEY ARE ADDED IN THE DOWNLOADER
DOWNLOADER_INJECTED_VARIABLES: Dict[Variable, str] = {
v.download_index: "{%int(1)}",
v.upload_date_index: "{%int(1)}",
v.comments: "{ [] }",
v.requested_subtitles: "{ {} }",
v.chapters: "{ [] }",
v.sponsorblock_chapters: "{ [] }",
v.ytdl_sub_input_url: f"{{{v.source_webpage_url.variable_name}}}",
}
ENTRY_DERIVED_VARIABLES: Dict[Variable, str] = {
v.uid_sanitized_plex: _sanitized_plex(v.uid),
v.title_sanitized_plex: _sanitized_plex(v.title),
v.epoch_date: f"{{%datetime_strftime({v.epoch.variable_name}, '%Y%m%d')}}",
v.epoch_hour: f"{{%datetime_strftime({v.epoch.variable_name}, '%H')}}",
v.download_index_padded6: _pad_int(v.download_index, 6),
v.upload_date_index_padded: _pad_int(v.upload_date_index, 2),
v.upload_date_index_reversed: f"{{%sub(100, {v.upload_date_index.variable_name})}}",
v.upload_date_index_reversed_padded: _pad_int(v.upload_date_index_reversed, 2),
v.playlist_index_reversed: (
f"{{%sub({v.playlist_count.variable_name}, {v.playlist_index.variable_name}, -1)}}"
),
v.playlist_index_padded: _pad_int(v.playlist_index, 2),
v.playlist_index_reversed_padded: _pad_int(v.playlist_index_reversed, 2),
v.playlist_index_padded6: _pad_int(v.playlist_index, 6),
v.playlist_index_reversed_padded6: _pad_int(v.playlist_index_reversed, 6),
}
ENTRY_UPLOAD_DATE_VARIABLES: Dict[Variable, str] = {
v.upload_year: _date_metadata(v.upload_date, "year"),
v.upload_year_truncated: _date_metadata(v.upload_date, "year_truncated"),
v.upload_year_truncated_reversed: _date_metadata(v.upload_date, "year_truncated_reversed"),
v.upload_month_reversed: _date_metadata(v.upload_date, "month_reversed"),
v.upload_month_reversed_padded: _date_metadata(v.upload_date, "month_reversed_padded"),
v.upload_month_padded: _date_metadata(v.upload_date, "month_padded"),
v.upload_day_padded: _date_metadata(v.upload_date, "day_padded"),
v.upload_month: _date_metadata(v.upload_date, "month"),
v.upload_day: _date_metadata(v.upload_date, "day"),
v.upload_day_reversed: _date_metadata(v.upload_date, "day_reversed"),
v.upload_day_reversed_padded: _date_metadata(v.upload_date, "day_reversed_padded"),
v.upload_day_of_year: _date_metadata(v.upload_date, "day_of_year"),
v.upload_day_of_year_padded: _date_metadata(v.upload_date, "day_of_year_padded"),
v.upload_day_of_year_reversed: _date_metadata(v.upload_date, "day_of_year_reversed"),
v.upload_day_of_year_reversed_padded: _date_metadata(
v.upload_date, "day_of_year_reversed_padded"
),
v.upload_date_standardized: _date_metadata(v.upload_date, "date_standardized"),
}
ENTRY_RELEASE_DATE_VARIABLES: Dict[Variable, str] = {
v.release_year: _date_metadata(v.release_date, "year"),
v.release_year_truncated: _date_metadata(v.release_date, "year_truncated"),
v.release_year_truncated_reversed: _date_metadata(v.release_date, "year_truncated_reversed"),
v.release_month_reversed: _date_metadata(v.release_date, "month_reversed"),
v.release_month_reversed_padded: _date_metadata(v.release_date, "month_reversed_padded"),
v.release_month_padded: _date_metadata(v.release_date, "month_padded"),
v.release_day_padded: _date_metadata(v.release_date, "day_padded"),
v.release_month: _date_metadata(v.release_date, "month"),
v.release_day: _date_metadata(v.release_date, "day"),
v.release_day_reversed: _date_metadata(v.release_date, "day_reversed"),
v.release_day_reversed_padded: _date_metadata(v.release_date, "day_reversed_padded"),
v.release_day_of_year: _date_metadata(v.release_date, "day_of_year"),
v.release_day_of_year_padded: _date_metadata(v.release_date, "day_of_year_padded"),
v.release_day_of_year_reversed: _date_metadata(v.release_date, "day_of_year_reversed"),
v.release_day_of_year_reversed_padded: _date_metadata(
v.release_date, "day_of_year_reversed_padded"
),
v.release_date_standardized: _date_metadata(v.release_date, "date_standardized"),
}
PLAYLIST_VARIABLES: Dict[Variable, str] = {
v.playlist_webpage_url: _playlist_get_str(v.playlist_webpage_url, v.webpage_url),
v.playlist_description: _playlist_get_str(v.playlist_description, v.description),
v.playlist_uploader: _playlist_get_str(v.playlist_uploader, v.uploader),
v.playlist_uploader_url: _playlist_get_str(v.playlist_uploader_url, v.playlist_webpage_url),
v.source_index: _playlist_get_int(v.source_index, 1),
v.source_count: _playlist_get_int(v.source_count, 1),
}
SOURCE_VARIABLES: Dict[Variable, str] = {
v.source_uid: _source_get_str(v.source_uid, v.playlist_uid),
v.source_title: _source_get_str(v.source_title, v.playlist_title),
v.source_webpage_url: _source_get_str(v.source_webpage_url, v.playlist_webpage_url),
v.source_description: _source_get_str(v.source_description, v.playlist_description),
v.source_uploader_id: _source_get_str(v.source_uploader_id, v.playlist_uploader_id),
v.source_uploader: _source_get_str(v.source_uploader, v.playlist_uploader),
v.source_uploader_url: _source_get_str(v.source_uploader_url, v.source_webpage_url),
}
SOURCE_DERIVED_VARIABLES: Dict[Variable, str] = {
v.source_index_padded: _pad_int(v.source_index, 2),
}
SIBLING_VARIABLES: Dict[Variable, str] = {
v.playlist_max_upload_date: f"""{{
%array_reduce(
%if_passthrough(
%extract_field_from_siblings('{v.upload_date.variable_name}'),
[{v.upload_date.variable_name}]
),
%max
)
}}"""
}
SIBLING_DERIVED_VARIABLES: Dict[Variable, str] = {
v.playlist_max_upload_year: _date_metadata(v.playlist_max_upload_date, "year"),
v.playlist_max_upload_year_truncated: _date_metadata(
v.playlist_max_upload_date, "year_truncated"
),
}
_VARIABLE_SCRIPTS: Dict[Variable, str] = {}
mergedeep.merge(
_VARIABLE_SCRIPTS,
ENTRY_EMPTY_METADATA,
ENTRY_HARDCODED_VARIABLES,
ENTRY_RELATIVE_VARIABLES,
ENTRY_REQUIRED_VARIABLES,
ENTRY_DEFAULT_VARIABLES,
DOWNLOADER_INJECTED_VARIABLES,
ENTRY_DERIVED_VARIABLES,
ENTRY_UPLOAD_DATE_VARIABLES,
ENTRY_RELEASE_DATE_VARIABLES,
SIBLING_VARIABLES,
SIBLING_DERIVED_VARIABLES,
PLAYLIST_VARIABLES,
SOURCE_VARIABLES,
SOURCE_DERIVED_VARIABLES,
)
VARIABLE_SCRIPTS: Dict[str, str] = {
var.variable_name: script for var, script in _VARIABLE_SCRIPTS.items()
}
def _keys(*variables: Dict[Variable, str]) -> Set[str]:
keys: Set[str] = set()
for variable_set in variables:
keys.update(set(var.variable_name for var in variable_set.keys()))
return keys
UNRESOLVED_VARIABLES: Set[str] = _keys(
ENTRY_EMPTY_METADATA,
DOWNLOADER_INJECTED_VARIABLES,
)
CustomFunctions.register()

View file

@ -0,0 +1,321 @@
from abc import ABC
from abc import abstractmethod
from dataclasses import dataclass
from typing import Dict
from typing import List
from typing import Optional
from typing import Type
from typing import TypeVar
from ytdl_sub.script.types.array import Array
from ytdl_sub.script.types.map import Map
from ytdl_sub.script.types.resolvable import Integer
from ytdl_sub.script.types.resolvable import String
ENTRY_METADATA_VARIABLE_NAME = "entry_metadata"
PLAYLIST_METADATA_VARIABLE_NAME = "playlist_metadata"
SOURCE_METADATA_VARIABLE_NAME = "source_metadata"
TMetadataVariable = TypeVar("TMetadataVariable", bound="MetadataVariable")
TVariable = TypeVar("TVariable", bound="Variable")
def _get(
cast: str,
metadata_variable_name: str,
metadata_key: str,
variable_name: Optional[str],
default: Optional[TVariable | str | int | Dict | List],
as_type: Type[TMetadataVariable],
) -> TMetadataVariable:
if default is None:
# TODO: assert with good error message if key DNE
out = f"%map_get({metadata_variable_name}, '{metadata_key}')"
elif isinstance(default, Variable):
args = f"{metadata_variable_name}, '{metadata_key}', {default.variable_name}"
out = f"%map_get_non_empty({args})"
elif isinstance(default, str):
out = f"%map_get_non_empty({metadata_variable_name}, '{metadata_key}', '{default}')"
elif isinstance(default, dict):
out = f"%map_get_non_empty({metadata_variable_name}, '{metadata_key}', {{}})"
elif isinstance(default, list):
out = f"%map_get_non_empty({metadata_variable_name}, '{metadata_key}', [])"
else:
out = f"%map_get_non_empty({metadata_variable_name}, '{metadata_key}', {default})"
return as_type(
variable_name=variable_name or metadata_key,
metadata_key=metadata_key,
definition=f"{{ %legacy_bracket_safety(%{cast}({out})) }}",
)
@dataclass(frozen=True)
class Variable(ABC):
variable_name: str
definition: str
@classmethod
@abstractmethod
def human_readable_type(cls) -> str:
"""
Script type of the variable, for documentation
"""
@dataclass(frozen=True)
class StringVariable(Variable):
@classmethod
def human_readable_type(cls) -> str:
return String.__name__
def to_sanitized_plex(self, variable_name: str) -> "StringVariable":
"""
Converts a String variable to be plex sanitized
"""
return StringVariable(
variable_name=variable_name,
definition=f"{{%sanitize_plex_episode({self.variable_name})}}",
)
def as_date_variable(self) -> "StringDateVariable":
"""
Converts a String variable to a date variable (which has metadata helpers)
"""
return StringDateVariable(
variable_name=self.variable_name,
definition=self.definition,
)
@dataclass(frozen=True)
class StringDateVariable(StringVariable):
def get_string_date_metadata(
self, date_metadata_key: str, variable_name: Optional[str] = None
) -> StringVariable:
"""
Gets a string-based date metadata variable
"""
return StringVariable(
variable_name=variable_name or date_metadata_key,
definition=f"""{{
%string(
%map_get(
%to_date_metadata({self.variable_name}),
'{date_metadata_key}'
)
)
}}""",
)
def get_integer_date_metadata(
self, date_metadata_key: str, variable_name: str
) -> "IntegerVariable":
"""
Gets an int-based date metadata variable
"""
return IntegerVariable(
variable_name=variable_name,
definition=f"""{{
%int(
%map_get(
%to_date_metadata({self.variable_name}),
'{date_metadata_key}'
)
)
}}""",
)
@dataclass(frozen=True)
class IntegerVariable(Variable):
@classmethod
def human_readable_type(cls) -> str:
return Integer.__name__
def to_padded_int(self, variable_name: str, pad: int) -> StringVariable:
"""
Pads an integer
"""
return StringVariable(
variable_name=variable_name, definition=f"{{%pad_zero({self.variable_name}, {pad})}}"
)
@dataclass(frozen=True)
class ArrayVariable(Variable):
@classmethod
def human_readable_type(cls) -> str:
return Array.__name__
@dataclass(frozen=True)
class MapVariable(Variable):
@classmethod
def human_readable_type(cls) -> str:
return Map.__name__
@dataclass(frozen=True)
class MetadataVariable(Variable, ABC):
metadata_key: str
@dataclass(frozen=True)
class MapMetadataVariable(MetadataVariable, MapVariable):
@classmethod
def from_entry(
cls,
metadata_key: str,
variable_name: Optional[str] = None,
default: Optional["MapMetadataVariable" | Dict] = None,
) -> "MapMetadataVariable":
"""
Creates a map variable from entry metadata
"""
return _get(
"map",
metadata_variable_name=ENTRY_METADATA_VARIABLE_NAME,
metadata_key=metadata_key,
variable_name=variable_name,
default=default,
as_type=MapMetadataVariable,
)
@dataclass(frozen=True)
class ArrayMetadataVariable(MetadataVariable, ArrayVariable):
@classmethod
def from_entry(
cls,
metadata_key: str,
variable_name: Optional[str] = None,
default: Optional["ArrayMetadataVariable" | List] = None,
) -> "ArrayMetadataVariable":
"""
Creates an array variable from entry metadata
"""
return _get(
"array",
metadata_variable_name=ENTRY_METADATA_VARIABLE_NAME,
metadata_key=metadata_key,
variable_name=variable_name,
default=default,
as_type=ArrayMetadataVariable,
)
@dataclass(frozen=True)
class StringMetadataVariable(MetadataVariable, StringVariable):
@classmethod
def from_entry(
cls,
metadata_key: str,
variable_name: Optional[str] = None,
default: Optional[StringVariable | str] = None,
) -> "StringMetadataVariable":
"""
Creates a string variable from entry metadata
"""
return _get(
"string",
metadata_variable_name=ENTRY_METADATA_VARIABLE_NAME,
metadata_key=metadata_key,
variable_name=variable_name,
default=default,
as_type=StringMetadataVariable,
)
@classmethod
def from_playlist(
cls,
metadata_key: str,
variable_name: Optional[str] = None,
default: Optional[StringVariable | str] = None,
) -> "StringMetadataVariable":
"""
Creates a string variable from playlist metadata
"""
return _get(
"string",
metadata_variable_name=PLAYLIST_METADATA_VARIABLE_NAME,
metadata_key=metadata_key,
variable_name=variable_name,
default=default,
as_type=StringMetadataVariable,
)
@classmethod
def from_source(
cls,
metadata_key: str,
variable_name: Optional[str] = None,
default: Optional[StringVariable | str] = None,
) -> "StringMetadataVariable":
"""
Creates a string variable from source metadata
"""
return _get(
"string",
metadata_variable_name=SOURCE_METADATA_VARIABLE_NAME,
metadata_key=metadata_key,
variable_name=variable_name,
default=default,
as_type=StringMetadataVariable,
)
def as_date_variable(self) -> "StringDateMetadataVariable":
"""
Converts a String variable to a date variable (which has metadata helpers)
"""
return StringDateMetadataVariable(
metadata_key=self.metadata_key,
variable_name=self.variable_name,
definition=self.definition,
)
@dataclass(frozen=True)
class StringDateMetadataVariable(StringMetadataVariable, StringDateVariable):
pass
@dataclass(frozen=True)
class IntegerMetadataVariable(MetadataVariable, IntegerVariable):
@classmethod
def from_entry(
cls,
metadata_key: str,
variable_name: Optional[str] = None,
default: Optional[IntegerVariable | int] = None,
) -> "IntegerMetadataVariable":
"""
Creates an int variable from entry metadata
"""
return _get(
"int",
metadata_variable_name=ENTRY_METADATA_VARIABLE_NAME,
metadata_key=metadata_key,
variable_name=variable_name,
default=default,
as_type=IntegerMetadataVariable,
)
@classmethod
def from_playlist(
cls,
metadata_key: str,
variable_name: Optional[str] = None,
default: Optional[IntegerVariable | int] = None,
) -> "IntegerMetadataVariable":
"""
Creates an int variable from playlist metadata
"""
return _get(
"int",
metadata_variable_name=PLAYLIST_METADATA_VARIABLE_NAME,
metadata_key=metadata_key,
variable_name=variable_name,
default=default,
as_type=IntegerMetadataVariable,
)

View file

@ -1,5 +1,5 @@
from ytdl_sub.entries.script.function_scripts import CUSTOM_FUNCTION_SCRIPTS
from ytdl_sub.entries.script.variable_scripts import VARIABLE_SCRIPTS
from ytdl_sub.entries.script.variable_definitions import VARIABLE_SCRIPTS
from ytdl_sub.script.functions import Functions
from ytdl_sub.script.utils.name_validation import is_valid_name

View file

@ -5,9 +5,9 @@ from typing import Dict
from typing import Set
from ytdl_sub.entries.script.function_scripts import CUSTOM_FUNCTION_SCRIPTS
from ytdl_sub.entries.script.variable_definitions import Variable
from ytdl_sub.entries.script.variable_scripts import UNRESOLVED_VARIABLES
from ytdl_sub.entries.script.variable_scripts import VARIABLE_SCRIPTS
from ytdl_sub.entries.script.variable_definitions import UNRESOLVED_VARIABLES
from ytdl_sub.entries.script.variable_definitions import VARIABLE_SCRIPTS
from ytdl_sub.entries.script.variable_types import Variable
from ytdl_sub.script.script import Script
from ytdl_sub.script.utils.exceptions import RuntimeException
from ytdl_sub.utils.exceptions import StringFormattingException

View file

@ -4,11 +4,12 @@ from typing import Dict
from typing import Type
from tools.docgen.docgen import DocGen
from tools.docgen.utils import cached_properties
from tools.docgen.utils import camel_case_to_human
from tools.docgen.utils import get_function_docs
from tools.docgen.utils import line_section
from tools.docgen.utils import properties
from tools.docgen.utils import section
from ytdl_sub.entries.script.variable_definitions import VARIABLES
from ytdl_sub.entries.script.variable_definitions import VariableDefinitions
@ -37,10 +38,11 @@ class EntryVariablesDocGen(DocGen):
docs += line_section(section_idx=idx)
docs += section(name, level=1)
for variable_function_name in properties(parent_objs[name]):
for variable_function_name in cached_properties(parent_objs[name]):
docs += get_function_docs(
function_name=variable_function_name,
obj=parent_objs[name],
pre_docstring=f":type: ``{getattr(VARIABLES, variable_function_name).human_readable_type()}``\n",
level=2,
)

View file

@ -1,4 +1,5 @@
import inspect
from functools import cached_property
from typing import Any
from typing import Dict
from typing import List
@ -18,6 +19,10 @@ def properties(obj: Type[Any]) -> List[str]:
return sorted(prop for prop in dir(obj) if isinstance(getattr(obj, prop), property))
def cached_properties(obj: Type[Any]) -> List[str]:
return sorted(prop for prop in dir(obj) if isinstance(getattr(obj, prop), cached_property))
def static_methods(obj: Type[Any]) -> List[str]:
return sorted(
name for name in dir(obj) if isinstance(inspect.getattr_static(obj, name), staticmethod)
@ -36,11 +41,16 @@ def camel_case_to_human(string: str) -> str:
def get_function_docs(
function_name: str, obj: Any, level: int, display_function_name: Optional[str] = None
function_name: str,
obj: Any,
level: int,
display_function_name: Optional[str] = None,
pre_docstring: Optional[str] = None,
) -> str:
display_function_name = display_function_name if display_function_name else function_name
docs = section(display_function_name, level=level)
docs += pre_docstring or ""
docs += inspect.cleandoc(getattr(obj, function_name).__doc__)
docs += "\n"
return docs