variables are king

This commit is contained in:
Jesse Bannon 2023-12-06 17:49:35 -08:00
parent 62e47b1d43
commit 62b07a3c2b
5 changed files with 56 additions and 64 deletions

View file

@ -3,6 +3,7 @@ from yt_dlp.utils import sanitize_filename
from ytdl_sub.script.functions import Functions from ytdl_sub.script.functions import Functions
from ytdl_sub.script.types.map import Map from ytdl_sub.script.types.map import Map
from ytdl_sub.script.types.resolvable import Integer from ytdl_sub.script.types.resolvable import Integer
from ytdl_sub.script.types.resolvable import ReturnableArgument
from ytdl_sub.script.types.resolvable import String from ytdl_sub.script.types.resolvable import String
from ytdl_sub.script.utils.exceptions import RuntimeException from ytdl_sub.script.utils.exceptions import RuntimeException
@ -15,14 +16,21 @@ _days_in_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
class CustomFunctions: class CustomFunctions:
@staticmethod
def legacy_bracket_safety(value: ReturnableArgument) -> ReturnableArgument:
if isinstance(value, String):
value = String(value.value.replace("{", "").replace("}", ""))
return value
@staticmethod @staticmethod
def sanitize(string: String) -> String: def sanitize(string: String) -> String:
return String(sanitize_filename(string.value)) return String(sanitize_filename(string.value))
@staticmethod @staticmethod
def sanitize_plex_episode(string: String) -> String: def sanitize_plex_episode(string: String) -> String:
out = CustomFunctions.sanitize(string).value sanitized_string = CustomFunctions.sanitize(string).value
for char in out: out = ""
for char in sanitized_string:
match char: match char:
case "0": case "0":
out += "" out += ""
@ -51,7 +59,7 @@ class CustomFunctions:
@staticmethod @staticmethod
def to_date_metadata(yyyymmdd: String) -> Map: def to_date_metadata(yyyymmdd: String) -> Map:
date_str = yyyymmdd.value date_str = yyyymmdd.value
if not (date_str.isnumeric() and len(date_str) == 6): if not (date_str.isnumeric() and len(date_str) == 8):
raise RuntimeException( raise RuntimeException(
f"Expected input of date_metadata to be YYYYMMDD, but received {date_str}" f"Expected input of date_metadata to be YYYYMMDD, but received {date_str}"
) )
@ -102,6 +110,7 @@ class CustomFunctions:
@staticmethod @staticmethod
def register(): def register():
Functions.register_function(CustomFunctions.legacy_bracket_safety)
Functions.register_function(CustomFunctions.sanitize) Functions.register_function(CustomFunctions.sanitize)
Functions.register_function(CustomFunctions.sanitize_plex_episode) Functions.register_function(CustomFunctions.sanitize_plex_episode)
Functions.register_function(CustomFunctions.to_date_metadata) Functions.register_function(CustomFunctions.to_date_metadata)

View file

@ -37,26 +37,6 @@ class _Variables:
""" """
return Metadata("entry_metadata") return Metadata("entry_metadata")
@property
def playlist_metadata(self) -> DerivedMetadata:
"""
Returns
-------
dict
The playlist's info.json in dict form
"""
return DerivedMetadata("playlist_metadata", metadata_key="playlist_metadata")
@property
def source_metadata(self) -> DerivedMetadata:
"""
Returns
-------
dict
The source's info.json in dict form
"""
return DerivedMetadata("source_metadata", metadata_key="source_metadata")
@property @property
def uid(self) -> MetadataVariable: def uid(self) -> MetadataVariable:
""" """
@ -238,7 +218,7 @@ class _Variables:
Name of the source (i.e. channel with multiple playlists) if it exists, otherwise Name of the source (i.e. channel with multiple playlists) if it exists, otherwise
returns its playlist_title. returns its playlist_title.
""" """
return MetadataVariable("source_title", metadata_key="title") return MetadataVariable("source_title", metadata_key="source_title")
@property @property
def source_title_sanitized(self) -> Variable: def source_title_sanitized(self) -> Variable:
@ -258,7 +238,7 @@ class _Variables:
str str
The source unique id if it exists, otherwise returns the playlist unique ID. The source unique id if it exists, otherwise returns the playlist unique ID.
""" """
return MetadataVariable("source_uid", metadata_key="id") return MetadataVariable("source_uid", metadata_key="source_uid")
@property @property
def source_index(self) -> MetadataVariable: def source_index(self) -> MetadataVariable:
@ -271,7 +251,7 @@ class _Variables:
It is recommended to not use this unless you know the source will never add new content 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 easy for this value to change).
""" """
return MetadataVariable("source_index", metadata_key="playlist_index") return MetadataVariable("source_index", metadata_key="source_index")
@property @property
def source_index_padded(self) -> Variable: def source_index_padded(self) -> Variable:
@ -291,7 +271,7 @@ class _Variables:
int int
The source count if it exists, otherwise returns the playlist count. The source count if it exists, otherwise returns the playlist count.
""" """
return MetadataVariable("source_count", metadata_key="playlist_count") return MetadataVariable("source_count", metadata_key="source_count")
@property @property
def source_webpage_url(self) -> MetadataVariable: def source_webpage_url(self) -> MetadataVariable:
@ -301,7 +281,7 @@ class _Variables:
str str
The source webpage url if it exists, otherwise returns the playlist webpage url. The source webpage url if it exists, otherwise returns the playlist webpage url.
""" """
return MetadataVariable("source_webpage_url", metadata_key="webpage_url") return MetadataVariable("source_webpage_url", metadata_key="source_webpage_url")
@property @property
def source_description(self) -> MetadataVariable: def source_description(self) -> MetadataVariable:
@ -311,7 +291,7 @@ class _Variables:
str str
The source description if it exists, otherwise returns the playlist description. The source description if it exists, otherwise returns the playlist description.
""" """
return MetadataVariable("source_description", metadata_key="description") return MetadataVariable("source_description", metadata_key="source_description")
@property @property
def playlist_uid(self) -> MetadataVariable: def playlist_uid(self) -> MetadataVariable:
@ -321,7 +301,7 @@ class _Variables:
str str
The playlist unique ID if it exists, otherwise return Variable("") The playlist unique ID if it exists, otherwise return Variable("")
""" """
return MetadataVariable(variable_name="playlist_uid", metadata_key="id") return MetadataVariable(variable_name="playlist_uid", metadata_key="playlist_uid")
@property @property
def playlist_title(self) -> MetadataVariable: def playlist_title(self) -> MetadataVariable:
@ -331,7 +311,7 @@ class _Variables:
str str
Name of its parent playlist/channel if it exists, otherwise returns its title. Name of its parent playlist/channel if it exists, otherwise returns its title.
""" """
return MetadataVariable(variable_name="playlist_title", metadata_key="title") return MetadataVariable(variable_name="playlist_title", metadata_key="playlist_title")
@property @property
def playlist_title_sanitized(self) -> Variable: def playlist_title_sanitized(self) -> Variable:
@ -427,7 +407,9 @@ class _Variables:
str str
The playlist description if it exists, otherwise returns the entry's description. The playlist description if it exists, otherwise returns the entry's description.
""" """
return MetadataVariable(variable_name="playlist_description", metadata_key="description") return MetadataVariable(
variable_name="playlist_description", metadata_key="playlist_description"
)
@property @property
def playlist_webpage_url(self) -> MetadataVariable: def playlist_webpage_url(self) -> MetadataVariable:
@ -437,7 +419,9 @@ class _Variables:
str str
The playlist webpage url if it exists. Otherwise, returns the entry webpage url. The playlist webpage url if it exists. Otherwise, returns the entry webpage url.
""" """
return MetadataVariable(variable_name="playlist_webpage_url", metadata_key="webpage_url") return MetadataVariable(
variable_name="playlist_webpage_url", metadata_key="playlist_webpage_url"
)
@property @property
def playlist_max_upload_year(self) -> MetadataVariable: def playlist_max_upload_year(self) -> MetadataVariable:
@ -472,7 +456,7 @@ class _Variables:
str str
The playlist uploader id if it exists, otherwise returns the entry uploader ID. The playlist uploader id if it exists, otherwise returns the entry uploader ID.
""" """
return MetadataVariable("playlist_uploader_id", metadata_key="uploader_id") return MetadataVariable("playlist_uploader_id", metadata_key="playlist_uploader_id")
@property @property
def playlist_uploader(self) -> MetadataVariable: def playlist_uploader(self) -> MetadataVariable:
@ -482,7 +466,7 @@ class _Variables:
str str
The playlist uploader if it exists, otherwise return Variable("") The playlist uploader if it exists, otherwise return Variable("")
""" """
return MetadataVariable("playlist_uploader", metadata_key="uploader") return MetadataVariable("playlist_uploader", metadata_key="playlist_uploader")
@property @property
def playlist_uploader_sanitized(self) -> Variable: def playlist_uploader_sanitized(self) -> Variable:
@ -502,7 +486,7 @@ class _Variables:
str str
The playlist uploader url if it exists, otherwise returns the playlist webpage_url. The playlist uploader url if it exists, otherwise returns the playlist webpage_url.
""" """
return MetadataVariable("playlist_uploader_url", metadata_key="uploader_url") return MetadataVariable("playlist_uploader_url", metadata_key="playlist_uploader_url")
@property @property
def source_uploader_id(self) -> MetadataVariable: def source_uploader_id(self) -> MetadataVariable:
@ -512,7 +496,7 @@ class _Variables:
str str
The source uploader id if it exists, otherwise returns the playlist_uploader_id The source uploader id if it exists, otherwise returns the playlist_uploader_id
""" """
return MetadataVariable("source_uploader_id", metadata_key="uploader_id") return MetadataVariable("source_uploader_id", metadata_key="source_uploader_id")
@property @property
def source_uploader(self) -> MetadataVariable: def source_uploader(self) -> MetadataVariable:
@ -522,7 +506,7 @@ class _Variables:
str str
The source uploader if it exists, otherwise return Variable("") The source uploader if it exists, otherwise return Variable("")
""" """
return MetadataVariable("source_uploader", metadata_key="uploader") return MetadataVariable("source_uploader", metadata_key="source_uploader")
@property @property
def source_uploader_url(self) -> MetadataVariable: def source_uploader_url(self) -> MetadataVariable:
@ -532,7 +516,7 @@ class _Variables:
str str
The source uploader url if it exists, otherwise returns the source webpage_url. The source uploader url if it exists, otherwise returns the source webpage_url.
""" """
return MetadataVariable("source_uploader_url", metadata_key="uploader_url") return MetadataVariable("source_uploader_url", metadata_key="source_uploader_url")
@property @property
def creator(self) -> MetadataVariable: def creator(self) -> MetadataVariable:

View file

@ -5,7 +5,6 @@ import mergedeep
from ytdl_sub.entries.script.function_scripts import CustomFunctions from ytdl_sub.entries.script.function_scripts import CustomFunctions
from ytdl_sub.entries.script.variable_definitions import VARIABLES as v from ytdl_sub.entries.script.variable_definitions import VARIABLES as v
from ytdl_sub.entries.script.variable_definitions import DerivedMetadata
from ytdl_sub.entries.script.variable_definitions import Metadata 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 MetadataVariable
from ytdl_sub.entries.script.variable_definitions import Variable from ytdl_sub.entries.script.variable_definitions import Variable
@ -39,13 +38,15 @@ def _get_internal(
) -> str: ) -> str:
if default is None: if default is None:
# TODO: assert with good error message if key DNE # TODO: assert with good error message if key DNE
return f"%map_get({metadata.variable_name}, '{key.metadata_key}')" out = f"%map_get({metadata.variable_name}, '{key.metadata_key}')"
if isinstance(default, Variable): elif isinstance(default, Variable):
return f"%map_get({metadata.variable_name}, '{key.metadata_key}', {default.variable_name})" out = f"%map_get({metadata.variable_name}, '{key.metadata_key}', {default.variable_name})"
if isinstance(default, str): elif isinstance(default, str):
return f"%map_get({metadata.variable_name}, '{key.metadata_key}', '{default}')" out = f"%map_get({metadata.variable_name}, '{key.metadata_key}', '{default}')"
else:
out = f"%map_get({metadata.variable_name}, '{key.metadata_key}', {default})"
return f"%map_get({metadata.variable_name}, '{key.metadata_key}', {default})" return f"%legacy_bracket_safety({out})"
def _get_int( def _get_int(
@ -75,11 +76,11 @@ def entry_get_int(key: MetadataVariable, default: Optional[Variable | int] = Non
def playlist_get(key: MetadataVariable, default: Optional[Variable | str | int] = None) -> str: def playlist_get(key: MetadataVariable, default: Optional[Variable | str | int] = None) -> str:
return _get(metadata=v.playlist_metadata, key=key, default=default) return _get(metadata=v.entry_metadata, key=key, default=default)
def playlist_get_int(key: MetadataVariable, default: Optional[Variable | int] = None) -> str: def playlist_get_int(key: MetadataVariable, default: Optional[Variable | int] = None) -> str:
return _get_int(metadata=v.playlist_metadata, key=key, default=default) return _get_int(metadata=v.entry_metadata, key=key, default=default)
############################################################################################### ###############################################################################################
@ -87,21 +88,16 @@ def playlist_get_int(key: MetadataVariable, default: Optional[Variable | int] =
def source_get(key: MetadataVariable, default: Optional[Variable | str | int] = None) -> str: def source_get(key: MetadataVariable, default: Optional[Variable | str | int] = None) -> str:
return _get(metadata=v.source_metadata, key=key, default=default) return _get(metadata=v.entry_metadata, key=key, default=default)
def source_get_int(key: MetadataVariable, default: Optional[Variable | int] = None) -> str: def source_get_int(key: MetadataVariable, default: Optional[Variable | int] = None) -> str:
return _get_int(metadata=v.source_metadata, key=key, default=default) return _get_int(metadata=v.entry_metadata, key=key, default=default)
############################################################################################### ###############################################################################################
# Scripts # Scripts
ENTRY_METADATA: Dict[DerivedMetadata, str] = {
v.playlist_metadata: entry_get(v.playlist_metadata),
v.source_metadata: entry_get(v.source_metadata),
}
ENTRY_HARDCODED_VARIABLES: Dict[Variable, str] = { ENTRY_HARDCODED_VARIABLES: Dict[Variable, str] = {
v.info_json_ext: "info.json", v.info_json_ext: "info.json",
@ -132,8 +128,8 @@ ENTRY_DEFAULT_VARIABLES: Dict[MetadataVariable, str] = {
} }
ENTRY_INJECTED_VARIABLES: Dict[MetadataVariable, str] = { ENTRY_INJECTED_VARIABLES: Dict[MetadataVariable, str] = {
v.download_index: entry_get_int(v.download_index), v.download_index: entry_get_int(v.download_index, 1),
v.upload_date_index: entry_get_int(v.upload_date_index), v.upload_date_index: entry_get_int(v.upload_date_index, 1),
} }
ENTRY_DERIVED_VARIABLES: Dict[Variable, str] = { ENTRY_DERIVED_VARIABLES: Dict[Variable, str] = {
@ -193,7 +189,7 @@ ENTRY_RELEASE_DATE_VARIABLES: Dict[Variable, str] = {
v.release_date_standardized: date_metadata(v.release_date, "date_standardized"), v.release_date_standardized: date_metadata(v.release_date, "date_standardized"),
} }
PLAYLIST_VARIABLES: Dict[MetadataVariable, str] = { PLAYLIST_VARIABLES: Dict[Variable, str] = {
v.playlist_uid: playlist_get(v.playlist_uid, v.uid), v.playlist_uid: playlist_get(v.playlist_uid, v.uid),
v.playlist_title: playlist_get(v.playlist_title, v.title), v.playlist_title: playlist_get(v.playlist_title, v.title),
v.playlist_webpage_url: playlist_get(v.playlist_webpage_url, v.webpage_url), v.playlist_webpage_url: playlist_get(v.playlist_webpage_url, v.webpage_url),
@ -204,13 +200,13 @@ PLAYLIST_VARIABLES: Dict[MetadataVariable, str] = {
v.playlist_uploader_url: playlist_get(v.playlist_uploader_url, v.playlist_webpage_url), v.playlist_uploader_url: playlist_get(v.playlist_uploader_url, v.playlist_webpage_url),
} }
PLAYLIST_INJECTED_VARIABLES: Dict[MetadataVariable, str] = { PLAYLIST_INJECTED_VARIABLES: Dict[Variable, str] = {
v.playlist_max_upload_year: playlist_get(v.playlist_max_upload_year, v.upload_year) v.playlist_max_upload_year: playlist_get(v.playlist_max_upload_year, v.upload_year)
} }
PLAYLIST_DERIVED_VARIABLES: Dict[Variable, str] = { PLAYLIST_DERIVED_VARIABLES: Dict[Variable, str] = {
v.playlist_title_sanitized: sanitized(v.playlist_title), v.playlist_title_sanitized: sanitized(v.playlist_title),
v.playlist_index_reversed: f"{{%sub({v.playlist_count.variable_name}, {v.playlist_index.variable_name}, 1)}}", 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_padded: pad_int(v.playlist_index, 2),
v.playlist_index_reversed_padded: pad_int(v.playlist_index_reversed, 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_padded6: pad_int(v.playlist_index, 6),
@ -220,7 +216,7 @@ PLAYLIST_DERIVED_VARIABLES: Dict[Variable, str] = {
} }
SOURCE_VARIABLES: Dict[MetadataVariable, str] = { SOURCE_VARIABLES: Dict[Variable, str] = {
v.source_uid: source_get(v.source_uid, v.playlist_uid), v.source_uid: source_get(v.source_uid, v.playlist_uid),
v.source_title: source_get(v.source_title, v.playlist_title), v.source_title: source_get(v.source_title, v.playlist_title),
v.source_webpage_url: source_get(v.source_webpage_url, v.playlist_webpage_url), v.source_webpage_url: source_get(v.source_webpage_url, v.playlist_webpage_url),
@ -240,7 +236,6 @@ SOURCE_DERIVED_VARIABLES: Dict[Variable, str] = {
_VARIABLE_SCRIPTS: Dict[Variable, str] = {} _VARIABLE_SCRIPTS: Dict[Variable, str] = {}
mergedeep.merge( mergedeep.merge(
_VARIABLE_SCRIPTS, _VARIABLE_SCRIPTS,
ENTRY_METADATA,
ENTRY_HARDCODED_VARIABLES, ENTRY_HARDCODED_VARIABLES,
ENTRY_REQUIRED_VARIABLES, ENTRY_REQUIRED_VARIABLES,
ENTRY_DEFAULT_VARIABLES, ENTRY_DEFAULT_VARIABLES,

View file

@ -162,6 +162,7 @@ def mock_entry_kwargs(
return { return {
"id": uid, "id": uid,
"epoch": 1596878400, "epoch": 1596878400,
"ie_key": "test_ie_key",
"extractor": extractor, "extractor": extractor,
"title": title, "title": title,
"ext": ext, "ext": ext,

View file

@ -11,5 +11,8 @@ class TestEntry(object):
entry_metadata: Dict[str, str] = { entry_metadata: Dict[str, str] = {
VARIABLES.entry_metadata.variable_name: f"{{{json.dumps(mock_entry._kwargs)}}}" VARIABLES.entry_metadata.variable_name: f"{{{json.dumps(mock_entry._kwargs)}}}"
} }
script = Script(dict(entry_metadata, **VARIABLE_SCRIPTS)).resolve() script = Script(dict(entry_metadata, **VARIABLE_SCRIPTS))
assert script == mock_entry_to_dict output = {var_name: var_output.native for var_name, var_output in script.resolve().items()}
del output[VARIABLES.entry_metadata.variable_name]
del output[VARIABLES.ie_key.variable_name]
assert output == mock_entry_to_dict