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:
|
my_example_preset:
|
||||||
overrides:
|
overrides:
|
||||||
output_directory: "/path/to/media"
|
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
|
# Then use the override variables in the output options
|
||||||
output_options:
|
output_options:
|
||||||
|
|
@ -55,19 +55,36 @@ class Overrides(DictFormatterValidator, Scriptable):
|
||||||
|
|
||||||
self.unresolvable.add(VARIABLES.entry_metadata.variable_name)
|
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] = {}
|
initial_variables: Dict[str, str] = {}
|
||||||
mergedeep.merge(
|
mergedeep.merge(
|
||||||
initial_variables,
|
initial_variables,
|
||||||
self.dict_with_format_strings,
|
self.dict_with_format_strings,
|
||||||
unresolved_variables,
|
unresolved_variables if unresolved_variables else {},
|
||||||
{SUBSCRIPTION_NAME: self.subscription_name},
|
{SUBSCRIPTION_NAME: self.subscription_name},
|
||||||
)
|
)
|
||||||
return ScriptUtils.add_sanitized_variables(initial_variables)
|
return ScriptUtils.add_sanitized_variables(initial_variables)
|
||||||
|
|
||||||
def initialize_script(self, unresolved_variables: Dict[str, str]) -> "Overrides":
|
def initialize_script(self, unresolved_variables: Set[str]) -> "Overrides":
|
||||||
self.script.add(self.initial_variables(unresolved_variables=unresolved_variables))
|
"""
|
||||||
self.unresolvable.update(set(unresolved_variables.keys()))
|
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()
|
self.update_script()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,11 @@ class PluginMapping:
|
||||||
def order_options_by(
|
def order_options_by(
|
||||||
cls, zipped: List[Tuple[Type[Plugin], OptionsValidator]], operation: PluginOperation
|
cls, zipped: List[Tuple[Type[Plugin], OptionsValidator]], operation: PluginOperation
|
||||||
) -> List[OptionsValidator]:
|
) -> List[OptionsValidator]:
|
||||||
|
"""
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Ordered plugin options with respect to the PluginOperation.
|
||||||
|
"""
|
||||||
ordered_types: List[Type[Plugin]] = cls._order_by(
|
ordered_types: List[Type[Plugin]] = cls._order_by(
|
||||||
plugin_types=[val[0] for val in zipped], operation=operation
|
plugin_types=[val[0] for val in zipped], operation=operation
|
||||||
)
|
)
|
||||||
|
|
@ -131,6 +136,12 @@ class PluginMapping:
|
||||||
def order_plugins_by(
|
def order_plugins_by(
|
||||||
cls, plugins: List[Plugin], operation: PluginOperation, before_split: Optional[bool] = None
|
cls, plugins: List[Plugin], operation: PluginOperation, before_split: Optional[bool] = None
|
||||||
) -> List[Plugin]:
|
) -> 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(
|
ordered_types: List[Type[Plugin]] = cls._order_by(
|
||||||
plugin_types=[type(plugin) for plugin in plugins], operation=operation
|
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]:
|
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]:
|
def _entry_variables() -> Set[str]:
|
||||||
|
|
@ -73,6 +73,9 @@ class VariableValidation:
|
||||||
self.unresolved_variables: Set[str] = set()
|
self.unresolved_variables: Set[str] = set()
|
||||||
|
|
||||||
def initialize_overrides(self, overrides: Overrides) -> "VariableValidation":
|
def initialize_overrides(self, overrides: Overrides) -> "VariableValidation":
|
||||||
|
"""
|
||||||
|
Do some gymnastics to initialize the Overrides script.
|
||||||
|
"""
|
||||||
entry_variables = _entry_variables()
|
entry_variables = _entry_variables()
|
||||||
override_variables = _override_variables(overrides)
|
override_variables = _override_variables(overrides)
|
||||||
|
|
||||||
|
|
@ -93,12 +96,7 @@ class VariableValidation:
|
||||||
# Initialize overrides with unresolved variables + modified variables to throw an error.
|
# 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
|
# For modified variables, this is to prevent a resolve(update=True) to setting any
|
||||||
# dependencies until it has been explicitly added
|
# dependencies until it has been explicitly added
|
||||||
overrides = overrides.initialize_script(
|
overrides = overrides.initialize_script(unresolved_variables=self.unresolved_variables)
|
||||||
unresolved_variables={
|
|
||||||
var_name: f"{{%throw('Plugin variable {var_name} has not been created yet')}}"
|
|
||||||
for var_name in self.unresolved_variables
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
# copy the script and mock entry variables
|
# copy the script and mock entry variables
|
||||||
self.script = copy.deepcopy(overrides.script).add(_add_dummy_variables(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()
|
self.update_script()
|
||||||
|
|
||||||
def initialize_script(self, other: Optional[Scriptable] = None) -> "Entry":
|
def initialize_script(self, other: Optional[Scriptable] = None) -> "Entry":
|
||||||
# TODO: CLEAN THIS SHIT UP
|
|
||||||
# Overrides contains added variables that are unresolvable, add them here
|
# Overrides contains added variables that are unresolvable, add them here
|
||||||
if other:
|
if other:
|
||||||
self.script = copy.deepcopy(other.script)
|
self.script = copy.deepcopy(other.script)
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ from ytdl_sub.entries.script.variable_scripts import ENTRY_REQUIRED_VARIABLES
|
||||||
v: VariableDefinitions = VARIABLES
|
v: VariableDefinitions = VARIABLES
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=protected-access
|
||||||
|
|
||||||
def _sort_entries(entries: List[TBaseEntry]) -> List[TBaseEntry]:
|
def _sort_entries(entries: List[TBaseEntry]) -> List[TBaseEntry]:
|
||||||
"""Try sorting by playlist_id first, then fall back to uid"""
|
"""Try sorting by playlist_id first, then fall back to uid"""
|
||||||
return sorted(
|
return sorted(
|
||||||
|
|
|
||||||
|
|
@ -23,24 +23,46 @@ _days_in_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
||||||
class CustomFunctions:
|
class CustomFunctions:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def legacy_bracket_safety(value: ReturnableArgument) -> ReturnableArgument:
|
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):
|
if isinstance(value, String):
|
||||||
value = String(value.value.replace("{", "{").replace("}", "}"))
|
value = String(value.value.replace("{", "{").replace("}", "}"))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def to_native_filepath(filepath: String) -> String:
|
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))
|
return String(filepath.value.replace(posixpath.sep, os.sep))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def truncate_filepath_if_too_long(filepath: String) -> String:
|
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))
|
return String(FilePathTruncater.maybe_truncate_file_path(filepath.value))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def sanitize(value: AnyArgument) -> String:
|
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)))
|
return String(sanitize_filename(str(value)))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def sanitize_plex_episode(string: String) -> String:
|
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
|
sanitized_string = CustomFunctions.sanitize(string).value
|
||||||
out = ""
|
out = ""
|
||||||
for char in sanitized_string:
|
for char in sanitized_string:
|
||||||
|
|
@ -71,6 +93,27 @@ class CustomFunctions:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def to_date_metadata(yyyymmdd: String) -> Map:
|
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
|
date_str = yyyymmdd.value
|
||||||
if not (date_str.isnumeric() and len(date_str) == 8):
|
if not (date_str.isnumeric() and len(date_str) == 8):
|
||||||
raise RuntimeException(
|
raise RuntimeException(
|
||||||
|
|
@ -123,6 +166,9 @@ class CustomFunctions:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def register():
|
def register():
|
||||||
|
"""
|
||||||
|
Register Custom functions once and only once
|
||||||
|
"""
|
||||||
if not Functions.is_built_in("sanitize"):
|
if not Functions.is_built_in("sanitize"):
|
||||||
Functions.register_function(CustomFunctions.legacy_bracket_safety)
|
Functions.register_function(CustomFunctions.legacy_bracket_safety)
|
||||||
Functions.register_function(CustomFunctions.truncate_filepath_if_too_long)
|
Functions.register_function(CustomFunctions.truncate_filepath_if_too_long)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue