refactor, linting
This commit is contained in:
parent
e171fd95c2
commit
57c8cb1ff5
6 changed files with 87 additions and 14 deletions
|
|
@ -28,7 +28,7 @@ class Overrides(DictFormatterValidator, Scriptable):
|
|||
my_example_preset:
|
||||
overrides:
|
||||
output_directory: "/path/to/media"
|
||||
custom_file_name: "{upload_year}.{upload_month_padded}.{upload_day_padded}.{title_sanitized}"
|
||||
custom_file_name: "{upload_date_standardized}.{title_sanitized}"
|
||||
|
||||
# Then use the override variables in the output options
|
||||
output_options:
|
||||
|
|
@ -55,19 +55,36 @@ class Overrides(DictFormatterValidator, Scriptable):
|
|||
|
||||
self.unresolvable.add(VARIABLES.entry_metadata.variable_name)
|
||||
|
||||
def initial_variables(self, unresolved_variables: Dict[str, str]) -> Dict[str, str]:
|
||||
def initial_variables(
|
||||
self, unresolved_variables: Optional[Dict[str, str]] = None
|
||||
) -> Dict[str, str]:
|
||||
"""
|
||||
Returns
|
||||
-------
|
||||
Variables and format strings for all Override variables + additional variables (Optional)
|
||||
"""
|
||||
initial_variables: Dict[str, str] = {}
|
||||
mergedeep.merge(
|
||||
initial_variables,
|
||||
self.dict_with_format_strings,
|
||||
unresolved_variables,
|
||||
unresolved_variables if unresolved_variables else {},
|
||||
{SUBSCRIPTION_NAME: self.subscription_name},
|
||||
)
|
||||
return ScriptUtils.add_sanitized_variables(initial_variables)
|
||||
|
||||
def initialize_script(self, unresolved_variables: Dict[str, str]) -> "Overrides":
|
||||
self.script.add(self.initial_variables(unresolved_variables=unresolved_variables))
|
||||
self.unresolvable.update(set(unresolved_variables.keys()))
|
||||
def initialize_script(self, unresolved_variables: Set[str]) -> "Overrides":
|
||||
"""
|
||||
Initialize the override script with override variables + any unresolved variables
|
||||
"""
|
||||
self.script.add(
|
||||
self.initial_variables(
|
||||
unresolved_variables={
|
||||
var_name: f"{{%throw('Plugin variable {var_name} has not been created yet')}}"
|
||||
for var_name in unresolved_variables
|
||||
}
|
||||
)
|
||||
)
|
||||
self.unresolvable.update(unresolved_variables)
|
||||
self.update_script()
|
||||
return self
|
||||
|
||||
|
|
|
|||
|
|
@ -108,6 +108,11 @@ class PluginMapping:
|
|||
def order_options_by(
|
||||
cls, zipped: List[Tuple[Type[Plugin], OptionsValidator]], operation: PluginOperation
|
||||
) -> List[OptionsValidator]:
|
||||
"""
|
||||
Returns
|
||||
-------
|
||||
Ordered plugin options with respect to the PluginOperation.
|
||||
"""
|
||||
ordered_types: List[Type[Plugin]] = cls._order_by(
|
||||
plugin_types=[val[0] for val in zipped], operation=operation
|
||||
)
|
||||
|
|
@ -131,6 +136,12 @@ class PluginMapping:
|
|||
def order_plugins_by(
|
||||
cls, plugins: List[Plugin], operation: PluginOperation, before_split: Optional[bool] = None
|
||||
) -> List[Plugin]:
|
||||
"""
|
||||
Returns
|
||||
-------
|
||||
Ordered plugins with respect to the PluginOperation. Optionally only return plugins
|
||||
before/after a split plugin.
|
||||
"""
|
||||
ordered_types: List[Type[Plugin]] = cls._order_by(
|
||||
plugin_types=[type(plugin) for plugin in plugins], operation=operation
|
||||
)
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ def _get_added_and_modified_variables(
|
|||
|
||||
|
||||
def _override_variables(overrides: Overrides) -> Set[str]:
|
||||
return set(list(overrides.initial_variables(unresolved_variables={}).keys()))
|
||||
return set(list(overrides.initial_variables().keys()))
|
||||
|
||||
|
||||
def _entry_variables() -> Set[str]:
|
||||
|
|
@ -73,6 +73,9 @@ class VariableValidation:
|
|||
self.unresolved_variables: Set[str] = set()
|
||||
|
||||
def initialize_overrides(self, overrides: Overrides) -> "VariableValidation":
|
||||
"""
|
||||
Do some gymnastics to initialize the Overrides script.
|
||||
"""
|
||||
entry_variables = _entry_variables()
|
||||
override_variables = _override_variables(overrides)
|
||||
|
||||
|
|
@ -93,12 +96,7 @@ class VariableValidation:
|
|||
# Initialize overrides with unresolved variables + modified variables to throw an error.
|
||||
# For modified variables, this is to prevent a resolve(update=True) to setting any
|
||||
# dependencies until it has been explicitly added
|
||||
overrides = overrides.initialize_script(
|
||||
unresolved_variables={
|
||||
var_name: f"{{%throw('Plugin variable {var_name} has not been created yet')}}"
|
||||
for var_name in self.unresolved_variables
|
||||
}
|
||||
)
|
||||
overrides = overrides.initialize_script(unresolved_variables=self.unresolved_variables)
|
||||
|
||||
# copy the script and mock entry variables
|
||||
self.script = copy.deepcopy(overrides.script).add(_add_dummy_variables(entry_variables))
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ class Entry(BaseEntry, Scriptable):
|
|||
self.update_script()
|
||||
|
||||
def initialize_script(self, other: Optional[Scriptable] = None) -> "Entry":
|
||||
# TODO: CLEAN THIS SHIT UP
|
||||
# Overrides contains added variables that are unresolvable, add them here
|
||||
if other:
|
||||
self.script = copy.deepcopy(other.script)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ from ytdl_sub.entries.script.variable_scripts import ENTRY_REQUIRED_VARIABLES
|
|||
v: VariableDefinitions = VARIABLES
|
||||
|
||||
|
||||
# pylint: disable=protected-access
|
||||
|
||||
def _sort_entries(entries: List[TBaseEntry]) -> List[TBaseEntry]:
|
||||
"""Try sorting by playlist_id first, then fall back to uid"""
|
||||
return sorted(
|
||||
|
|
|
|||
|
|
@ -23,24 +23,46 @@ _days_in_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
|||
class CustomFunctions:
|
||||
@staticmethod
|
||||
def legacy_bracket_safety(value: ReturnableArgument) -> ReturnableArgument:
|
||||
"""
|
||||
ytdl-sub used to replace brackets ('{', '}') with unicode brackets ('{', '}') to not
|
||||
interfere with its legacy variable scripting system. This function replicates that
|
||||
behavior.
|
||||
"""
|
||||
if isinstance(value, String):
|
||||
value = String(value.value.replace("{", "{").replace("}", "}"))
|
||||
return value
|
||||
|
||||
@staticmethod
|
||||
def to_native_filepath(filepath: String) -> String:
|
||||
"""
|
||||
Convert any unix-based path separators ('/') with the OS's native
|
||||
separator.
|
||||
"""
|
||||
return String(filepath.value.replace(posixpath.sep, os.sep))
|
||||
|
||||
@staticmethod
|
||||
def truncate_filepath_if_too_long(filepath: String) -> String:
|
||||
"""
|
||||
If a file-path is too long for the OS, this function will truncate it while preserving
|
||||
the extension.
|
||||
"""
|
||||
return String(FilePathTruncater.maybe_truncate_file_path(filepath.value))
|
||||
|
||||
@staticmethod
|
||||
def sanitize(value: AnyArgument) -> String:
|
||||
"""
|
||||
Sanitize a string using yt-dlp's ``sanitize_filename`` method to ensure it's safe to use
|
||||
for file/directory names on any OS.
|
||||
"""
|
||||
return String(sanitize_filename(str(value)))
|
||||
|
||||
@staticmethod
|
||||
def sanitize_plex_episode(string: String) -> String:
|
||||
"""
|
||||
Sanitize a string using ``sanitize`` and replace numerics with their respective fixed-width
|
||||
numbers. This is used to have Plex avoid scraping numbers like ``4x4`` as the
|
||||
season and/or episode.
|
||||
"""
|
||||
sanitized_string = CustomFunctions.sanitize(string).value
|
||||
out = ""
|
||||
for char in sanitized_string:
|
||||
|
|
@ -71,6 +93,27 @@ class CustomFunctions:
|
|||
|
||||
@staticmethod
|
||||
def to_date_metadata(yyyymmdd: String) -> Map:
|
||||
"""
|
||||
Takes a date in the form of YYYYMMDD and returns a Map containing:
|
||||
|
||||
- date (String, YYYYMMDD)
|
||||
- date_standardized (String, YYYY-MM-DD)
|
||||
- year (Integer)
|
||||
- month (Integer)
|
||||
- day (Integer)
|
||||
- year_truncated (String, YY from YY[YY])
|
||||
- month_padded (String)
|
||||
- day_padded (String)
|
||||
- year_truncated_reversed (Integer, 100 - year_truncated)
|
||||
- month_reversed (Integer, 13 - month)
|
||||
- month_reversed_padded (String)
|
||||
- day_reversed (Integer, total_days_in_month + 1 - day)
|
||||
- day_reversed_padded (String)
|
||||
- day_of_year (Integer)
|
||||
- day_of_year_padded (String, padded 3)
|
||||
- day_of_year_reversed (Integer, total_days_in_year + 1 - day_of_year)
|
||||
- day_of_year_reversed_padded (String, padded 3)
|
||||
"""
|
||||
date_str = yyyymmdd.value
|
||||
if not (date_str.isnumeric() and len(date_str) == 8):
|
||||
raise RuntimeException(
|
||||
|
|
@ -123,6 +166,9 @@ class CustomFunctions:
|
|||
|
||||
@staticmethod
|
||||
def register():
|
||||
"""
|
||||
Register Custom functions once and only once
|
||||
"""
|
||||
if not Functions.is_built_in("sanitize"):
|
||||
Functions.register_function(CustomFunctions.legacy_bracket_safety)
|
||||
Functions.register_function(CustomFunctions.truncate_filepath_if_too_long)
|
||||
|
|
|
|||
Loading…
Reference in a new issue