return string formatters in overrides dict
This commit is contained in:
parent
288e5cb892
commit
451b3564c5
11 changed files with 170 additions and 53 deletions
|
|
@ -1,6 +1,9 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ytdl_subscribe.entries.entry import Entry
|
from ytdl_subscribe.entries.entry import Entry
|
||||||
|
from ytdl_subscribe.validators.base.string_formatter_validators import (
|
||||||
|
StringFormatterValidator,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
@ -110,7 +113,12 @@ def validate_entry_dict_contains_valid_formatters():
|
||||||
expected_string = f"test {value} formatting works"
|
expected_string = f"test {value} formatting works"
|
||||||
format_string = f"test {{{key}}} formatting works"
|
format_string = f"test {{{key}}} formatting works"
|
||||||
|
|
||||||
assert entry.apply_formatter(format_string) == expected_string
|
assert (
|
||||||
|
entry.apply_formatter(
|
||||||
|
StringFormatterValidator(name="test", value=format_string)
|
||||||
|
)
|
||||||
|
== expected_string
|
||||||
|
)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,13 @@ import tempfile
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from ytdl_subscribe.validators.base.string_formatter_validators import (
|
||||||
|
StringFormatterValidator,
|
||||||
|
)
|
||||||
|
from ytdl_subscribe.validators.config.overrides.overrides_validator import (
|
||||||
|
OverridesValidator,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestEntry(object):
|
class TestEntry(object):
|
||||||
def test_entry_properties(
|
def test_entry_properties(
|
||||||
|
|
@ -30,13 +37,17 @@ class TestEntry(object):
|
||||||
relative_directory.cleanup()
|
relative_directory.cleanup()
|
||||||
|
|
||||||
def test_entry_formatter_single_field(self, mock_entry):
|
def test_entry_formatter_single_field(self, mock_entry):
|
||||||
format_string = f"prefix {{uid}} suffix"
|
format_string = StringFormatterValidator(
|
||||||
|
name="test", value=f"prefix {{uid}} suffix"
|
||||||
|
)
|
||||||
expected_string = f"prefix {mock_entry.uid} suffix"
|
expected_string = f"prefix {mock_entry.uid} suffix"
|
||||||
|
|
||||||
assert mock_entry.apply_formatter(format_string) == expected_string
|
assert mock_entry.apply_formatter(format_string) == expected_string
|
||||||
|
|
||||||
def test_entry_formatter_duplicate_fields(self, mock_entry):
|
def test_entry_formatter_duplicate_fields(self, mock_entry):
|
||||||
format_string = f"prefix {{upload_year}} {{upload_year}} suffix"
|
format_string = StringFormatterValidator(
|
||||||
|
name="test", value=f"prefix {{upload_year}} {{upload_year}} suffix"
|
||||||
|
)
|
||||||
expected_string = (
|
expected_string = (
|
||||||
f"prefix {mock_entry.upload_year} {mock_entry.upload_year} suffix"
|
f"prefix {mock_entry.upload_year} {mock_entry.upload_year} suffix"
|
||||||
)
|
)
|
||||||
|
|
@ -45,9 +56,11 @@ class TestEntry(object):
|
||||||
|
|
||||||
def test_entry_formatter_override(self, mock_entry):
|
def test_entry_formatter_override(self, mock_entry):
|
||||||
new_uid = "my very own uid"
|
new_uid = "my very own uid"
|
||||||
overrides = {"uid": new_uid}
|
overrides = OverridesValidator(name="test", value={"uid": new_uid})
|
||||||
|
|
||||||
format_string = f"prefix {{uid}} suffix"
|
format_string = StringFormatterValidator(
|
||||||
|
name="test", value=f"prefix {{uid}} suffix"
|
||||||
|
)
|
||||||
expected_string = f"prefix {new_uid} suffix"
|
expected_string = f"prefix {new_uid} suffix"
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
|
|
@ -64,7 +77,9 @@ class TestEntry(object):
|
||||||
mock_entry.kwargs(key)
|
mock_entry.kwargs(key)
|
||||||
|
|
||||||
def test_entry_formatter_fails_missing_field(self, mock_entry):
|
def test_entry_formatter_fails_missing_field(self, mock_entry):
|
||||||
format_string = f"prefix {{bah_humbug}} suffix"
|
format_string = StringFormatterValidator(
|
||||||
|
name="test", value=f"prefix {{bah_humbug}} suffix"
|
||||||
|
)
|
||||||
available_fields = ", ".join(sorted(mock_entry.to_dict().keys()))
|
available_fields = ", ".join(sorted(mock_entry.to_dict().keys()))
|
||||||
expected_error_msg = f"Format variable 'bah_humbug' does not exist for Entry. Available fields: {available_fields}"
|
expected_error_msg = f"Format variable 'bah_humbug' does not exist for Entry. Available fields: {available_fields}"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ytdl_subscribe.validators.base.string_formatter_validator import (
|
from ytdl_subscribe.validators.base.string_formatter_validators import (
|
||||||
|
DictFormatterValidator,
|
||||||
|
)
|
||||||
|
from ytdl_subscribe.validators.base.string_formatter_validators import (
|
||||||
StringFormatterValidator,
|
StringFormatterValidator,
|
||||||
)
|
)
|
||||||
from ytdl_subscribe.validators.exceptions import ValidationException
|
from ytdl_subscribe.validators.exceptions import ValidationException
|
||||||
|
|
@ -22,14 +25,17 @@ def error_message_unequal_regex_matches_str():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestEntryFormatter(object):
|
class TestStringFormatterValidator(object):
|
||||||
def test_parse(self):
|
def test_parse(self):
|
||||||
format_string = "Here is my {var_one} and {var_two} 💩"
|
format_string = "Here is my {var_one} and {var_two} 💩"
|
||||||
assert StringFormatterValidator(
|
validator = StringFormatterValidator(
|
||||||
name="test_format_variables", value=format_string
|
name="test_format_variables", value=format_string
|
||||||
).format_variables == ["var_one", "var_two"]
|
)
|
||||||
|
|
||||||
def test_parse_no_variables(self):
|
assert validator.format_string == format_string
|
||||||
|
assert validator.format_variables == ["var_one", "var_two"]
|
||||||
|
|
||||||
|
def test_format_variables(self):
|
||||||
format_string = "No vars 💩"
|
format_string = "No vars 💩"
|
||||||
assert (
|
assert (
|
||||||
StringFormatterValidator(
|
StringFormatterValidator(
|
||||||
|
|
@ -47,7 +53,7 @@ class TestEntryFormatter(object):
|
||||||
"Try }var_one} and {var_one}",
|
"Try }var_one} and {var_one}",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_parse_fail_uneven_brackets(
|
def test_validate_fail_uneven_brackets(
|
||||||
self, format_string, error_message_unequal_brackets_str
|
self, format_string, error_message_unequal_brackets_str
|
||||||
):
|
):
|
||||||
expected_error_msg = (
|
expected_error_msg = (
|
||||||
|
|
@ -60,15 +66,15 @@ class TestEntryFormatter(object):
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"format_string",
|
"format_string",
|
||||||
[
|
[
|
||||||
"Try {var1} no numbers",
|
"Try {var1} numbers",
|
||||||
"Try {VAR1} no caps",
|
"Try {VAR1} caps w/numbers",
|
||||||
"Try {internal{bracket}}",
|
"Try {internal{bracket}}",
|
||||||
"Try }backwards{ facing",
|
"Try }backwards{ facing",
|
||||||
"Try {var_1}}{",
|
"Try {var_1}}{",
|
||||||
"Try {} empty",
|
"Try {} empty",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_parse_fail_variable(
|
def test_validate_fail_bad_variable(
|
||||||
self, format_string, error_message_unequal_regex_matches_str
|
self, format_string, error_message_unequal_regex_matches_str
|
||||||
):
|
):
|
||||||
expected_error_msg = (
|
expected_error_msg = (
|
||||||
|
|
@ -77,3 +83,37 @@ class TestEntryFormatter(object):
|
||||||
|
|
||||||
with pytest.raises(ValidationException, match=expected_error_msg):
|
with pytest.raises(ValidationException, match=expected_error_msg):
|
||||||
_ = StringFormatterValidator(name="fail", value=format_string)
|
_ = StringFormatterValidator(name="fail", value=format_string)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"format_string, bad_variable",
|
||||||
|
[
|
||||||
|
("keyword {while}", "while"),
|
||||||
|
("{try} {valid_var}", "try"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_validate_fail_variable_keyword_or_not_identifier(
|
||||||
|
self, format_string, bad_variable
|
||||||
|
):
|
||||||
|
expected_error_msg = (
|
||||||
|
f"Validation error in fail: "
|
||||||
|
f"'{bad_variable}' is a Python keyword and cannot be used as a variable."
|
||||||
|
)
|
||||||
|
|
||||||
|
with pytest.raises(ValidationException, match=expected_error_msg):
|
||||||
|
_ = StringFormatterValidator(name="fail", value=format_string)
|
||||||
|
|
||||||
|
|
||||||
|
class TestDictFormatterValidator(object):
|
||||||
|
def test_validates_values(self):
|
||||||
|
key1_format_string = "string with {variable}"
|
||||||
|
key2_format_string = "no variables"
|
||||||
|
validator = DictFormatterValidator(
|
||||||
|
name="validator",
|
||||||
|
value={"key1": key1_format_string, "key2": key2_format_string},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert validator.dict["key1"].format_string == key1_format_string
|
||||||
|
assert validator.dict["key2"].format_string == key2_format_string
|
||||||
|
|
||||||
|
assert validator.dict["key1"].format_variables == ["variable"]
|
||||||
|
assert validator.dict["key2"].format_variables == []
|
||||||
|
|
@ -5,9 +5,12 @@ from typing import Optional
|
||||||
|
|
||||||
from sanitize_filename import sanitize
|
from sanitize_filename import sanitize
|
||||||
|
|
||||||
from ytdl_subscribe.validators.base.string_formatter_validator import (
|
from ytdl_subscribe.validators.base.string_formatter_validators import (
|
||||||
StringFormatterValidator,
|
StringFormatterValidator,
|
||||||
)
|
)
|
||||||
|
from ytdl_subscribe.validators.config.overrides.overrides_validator import (
|
||||||
|
OverridesValidator,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Entry:
|
class Entry:
|
||||||
|
|
@ -105,7 +108,9 @@ class Entry:
|
||||||
}
|
}
|
||||||
|
|
||||||
def apply_formatter(
|
def apply_formatter(
|
||||||
self, format_string: str, overrides: Optional[Dict] = None
|
self,
|
||||||
|
formatter: StringFormatterValidator,
|
||||||
|
overrides: Optional[OverridesValidator] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Perform a string format on the given format string, using the entry's dict for format
|
Perform a string format on the given format string, using the entry's dict for format
|
||||||
|
|
@ -113,13 +118,10 @@ class Entry:
|
||||||
"""
|
"""
|
||||||
entry_dict = self.to_dict()
|
entry_dict = self.to_dict()
|
||||||
if overrides:
|
if overrides:
|
||||||
entry_dict = dict(entry_dict, **overrides)
|
# TODO: need to check recursively populate format variables
|
||||||
|
entry_dict = dict(entry_dict, **overrides.dict_with_format_strings)
|
||||||
|
|
||||||
field_names = StringFormatterValidator(
|
for field_name in formatter.format_variables:
|
||||||
"TODO: UPDATE", format_string
|
|
||||||
).format_variables
|
|
||||||
|
|
||||||
for field_name in field_names:
|
|
||||||
if field_name not in entry_dict:
|
if field_name not in entry_dict:
|
||||||
available_fields = ", ".join(sorted(entry_dict.keys()))
|
available_fields = ", ".join(sorted(entry_dict.keys()))
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
|
@ -127,4 +129,4 @@ class Entry:
|
||||||
f"for {self.__class__.__name__}. Available fields: {available_fields}"
|
f"for {self.__class__.__name__}. Available fields: {available_fields}"
|
||||||
)
|
)
|
||||||
|
|
||||||
return format_string.format(**entry_dict)
|
return formatter.format_string.format(**entry_dict)
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@ from PIL import Image
|
||||||
|
|
||||||
from ytdl_subscribe.downloaders.downloader import Downloader
|
from ytdl_subscribe.downloaders.downloader import Downloader
|
||||||
from ytdl_subscribe.entries.entry import Entry
|
from ytdl_subscribe.entries.entry import Entry
|
||||||
|
from ytdl_subscribe.validators.base.string_formatter_validators import (
|
||||||
|
StringFormatterValidator,
|
||||||
|
)
|
||||||
from ytdl_subscribe.validators.config.config_options.config_options_validator import (
|
from ytdl_subscribe.validators.config.config_options.config_options_validator import (
|
||||||
ConfigOptionsValidator,
|
ConfigOptionsValidator,
|
||||||
)
|
)
|
||||||
|
|
@ -80,14 +83,31 @@ class Subscription(object):
|
||||||
ytdl_options=self.ytdl_options.dict,
|
ytdl_options=self.ytdl_options.dict,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _apply_entry_formatter(
|
||||||
|
self, entry: Entry, formatter: StringFormatterValidator
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
entry
|
||||||
|
Entry with values to use in the formatter
|
||||||
|
formatter
|
||||||
|
The formatter itself
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
The format_string after .format has been called on it using entry and override values
|
||||||
|
"""
|
||||||
|
return entry.apply_formatter(formatter=formatter, overrides=self.overrides)
|
||||||
|
|
||||||
def _post_process_tagging(self, entry: Entry):
|
def _post_process_tagging(self, entry: Entry):
|
||||||
id3_options = self.metadata_options.id3
|
id3_options = self.metadata_options.id3
|
||||||
audio_file = music_tag.load_file(
|
audio_file = music_tag.load_file(
|
||||||
entry.file_path(relative_directory=self.working_directory)
|
entry.file_path(relative_directory=self.working_directory)
|
||||||
)
|
)
|
||||||
for tag, tag_formatter in id3_options.tags.dict.items():
|
for tag, tag_formatter in id3_options.tags.dict.items():
|
||||||
audio_file[tag] = entry.apply_formatter(
|
audio_file[tag] = self._apply_entry_formatter(
|
||||||
format_string=tag_formatter, overrides=self.overrides.dict
|
entry=entry, formatter=tag_formatter
|
||||||
)
|
)
|
||||||
audio_file.save()
|
audio_file.save()
|
||||||
|
|
||||||
|
|
@ -96,24 +116,28 @@ class Subscription(object):
|
||||||
nfo_options = self.metadata_options.nfo
|
nfo_options = self.metadata_options.nfo
|
||||||
|
|
||||||
for tag, tag_formatter in nfo_options.tags.dict.items():
|
for tag, tag_formatter in nfo_options.tags.dict.items():
|
||||||
nfo[tag] = entry.apply_formatter(
|
nfo[tag] = self._apply_entry_formatter(entry=entry, formatter=tag_formatter)
|
||||||
format_string=tag_formatter, overrides=self.overrides.dict
|
|
||||||
)
|
|
||||||
|
|
||||||
|
# Write the nfo tags to XML with the nfo_root
|
||||||
|
nfo_root = self._apply_entry_formatter(
|
||||||
|
entry=entry, formatter=nfo_options.nfo_root
|
||||||
|
)
|
||||||
xml = dicttoxml.dicttoxml(
|
xml = dicttoxml.dicttoxml(
|
||||||
obj=nfo,
|
obj=nfo,
|
||||||
root=True, # We assume all NFOs have a root. Maybe we should not?
|
root=True, # We assume all NFOs have a root. Maybe we should not?
|
||||||
custom_root=nfo_options.nfo_root.value,
|
custom_root=nfo_root,
|
||||||
attr_type=False,
|
attr_type=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
nfo_file_name = entry.apply_formatter(
|
nfo_file_name = self._apply_entry_formatter(
|
||||||
format_string=nfo_options.nfo_name.format_string,
|
entry=entry, formatter=nfo_options.nfo_name
|
||||||
overrides=self.overrides.dict,
|
|
||||||
)
|
)
|
||||||
nfo_file_path = Path(self.output_options.output_directory.value) / Path(
|
output_directory = self._apply_entry_formatter(
|
||||||
nfo_file_name
|
entry=entry, formatter=self.output_options.output_directory
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Save the nfo's XML to file
|
||||||
|
nfo_file_path = Path(output_directory) / Path(nfo_file_name)
|
||||||
with open(nfo_file_path, "wb") as nfo_file:
|
with open(nfo_file_path, "wb") as nfo_file:
|
||||||
nfo_file.write(xml)
|
nfo_file.write(xml)
|
||||||
|
|
||||||
|
|
@ -132,13 +156,12 @@ class Subscription(object):
|
||||||
relative_directory=self.working_directory
|
relative_directory=self.working_directory
|
||||||
)
|
)
|
||||||
|
|
||||||
output_directory = entry.apply_formatter(
|
output_directory = self._apply_entry_formatter(
|
||||||
format_string=self.output_options.output_directory.format_string,
|
entry=entry, formatter=self.output_options.output_directory
|
||||||
overrides=self.overrides.dict,
|
|
||||||
)
|
)
|
||||||
output_file_name = entry.apply_formatter(
|
|
||||||
format_string=self.output_options.file_name.format_string,
|
output_file_name = self._apply_entry_formatter(
|
||||||
overrides=self.overrides.dict,
|
entry=entry, formatter=self.output_options.file_name
|
||||||
)
|
)
|
||||||
entry_destination_file_path = Path(output_directory) / Path(output_file_name)
|
entry_destination_file_path = Path(output_directory) / Path(output_file_name)
|
||||||
|
|
||||||
|
|
@ -151,9 +174,8 @@ class Subscription(object):
|
||||||
relative_directory=self.working_directory
|
relative_directory=self.working_directory
|
||||||
)
|
)
|
||||||
|
|
||||||
output_thumbnail_name = entry.apply_formatter(
|
output_thumbnail_name = self._apply_entry_formatter(
|
||||||
format_string=self.output_options.thumbnail_name.format_string,
|
entry=entry, formatter=self.output_options.thumbnail_name
|
||||||
overrides=self.overrides.dict,
|
|
||||||
)
|
)
|
||||||
output_thumbnail_path = Path(output_directory) / Path(output_thumbnail_name)
|
output_thumbnail_path = Path(output_directory) / Path(output_thumbnail_name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import re
|
import re
|
||||||
from keyword import iskeyword
|
from keyword import iskeyword
|
||||||
|
from typing import Dict
|
||||||
from typing import List
|
from typing import List
|
||||||
from typing import final
|
from typing import final
|
||||||
|
|
||||||
|
|
@ -80,4 +81,19 @@ class DictFormatterValidator(LiteralDictValidator):
|
||||||
super().__init__(name, value)
|
super().__init__(name, value)
|
||||||
|
|
||||||
for key in self._keys:
|
for key in self._keys:
|
||||||
_ = self._validate_key(key=key, validator=StringFormatterValidator)
|
self._value[key] = self._validate_key(
|
||||||
|
key=key, validator=StringFormatterValidator
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dict(self) -> Dict[str, StringFormatterValidator]:
|
||||||
|
"""Returns dict with string formatter values"""
|
||||||
|
return self._value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dict_with_format_strings(self) -> Dict[str, str]:
|
||||||
|
"""Returns dict with the format strings themselves"""
|
||||||
|
return {
|
||||||
|
key: string_formatter.format_string
|
||||||
|
for key, string_formatter in self.dict.items()
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import copy
|
||||||
from abc import ABC
|
from abc import ABC
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
@ -25,7 +26,9 @@ class Validator(ABC):
|
||||||
|
|
||||||
def __init__(self, name: str, value: Any):
|
def __init__(self, name: str, value: Any):
|
||||||
self._name = name
|
self._name = name
|
||||||
self._value = value
|
self._value = copy.deepcopy(
|
||||||
|
value
|
||||||
|
) # Always deep copy to avoid editing references
|
||||||
|
|
||||||
if not isinstance(self._value, self._expected_value_type):
|
if not isinstance(self._value, self._expected_value_type):
|
||||||
expected_value_type_name = self._expected_value_type_name or str(
|
expected_value_type_name = self._expected_value_type_name or str(
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from ytdl_subscribe.validators.base.strict_dict_validator import StrictDictValidator
|
from ytdl_subscribe.validators.base.strict_dict_validator import StrictDictValidator
|
||||||
from ytdl_subscribe.validators.base.string_formatter_validator import (
|
from ytdl_subscribe.validators.base.string_formatter_validators import (
|
||||||
DictFormatterValidator,
|
DictFormatterValidator,
|
||||||
)
|
)
|
||||||
from ytdl_subscribe.validators.base.string_select_validator import StringSelectValidator
|
from ytdl_subscribe.validators.base.string_select_validator import StringSelectValidator
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
from ytdl_subscribe.validators.base.strict_dict_validator import StrictDictValidator
|
from ytdl_subscribe.validators.base.strict_dict_validator import StrictDictValidator
|
||||||
from ytdl_subscribe.validators.base.string_formatter_validator import (
|
from ytdl_subscribe.validators.base.string_formatter_validators import (
|
||||||
DictFormatterValidator,
|
DictFormatterValidator,
|
||||||
)
|
)
|
||||||
from ytdl_subscribe.validators.base.string_formatter_validator import (
|
from ytdl_subscribe.validators.base.string_formatter_validators import (
|
||||||
StringFormatterValidator,
|
StringFormatterValidator,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from ytdl_subscribe.validators.base.strict_dict_validator import StrictDictValidator
|
from ytdl_subscribe.validators.base.strict_dict_validator import StrictDictValidator
|
||||||
from ytdl_subscribe.validators.base.string_formatter_validator import (
|
from ytdl_subscribe.validators.base.string_formatter_validators import (
|
||||||
StringFormatterValidator,
|
StringFormatterValidator,
|
||||||
)
|
)
|
||||||
from ytdl_subscribe.validators.base.string_select_validator import StringSelectValidator
|
from ytdl_subscribe.validators.base.string_select_validator import StringSelectValidator
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
import sanitize_filename
|
import sanitize_filename
|
||||||
|
|
||||||
from ytdl_subscribe.validators.base.string_formatter_validator import (
|
from ytdl_subscribe.validators.base.string_formatter_validators import (
|
||||||
DictFormatterValidator,
|
DictFormatterValidator,
|
||||||
)
|
)
|
||||||
|
from ytdl_subscribe.validators.base.string_formatter_validators import (
|
||||||
|
StringFormatterValidator,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class OverridesValidator(DictFormatterValidator):
|
class OverridesValidator(DictFormatterValidator):
|
||||||
|
|
@ -11,6 +14,14 @@ class OverridesValidator(DictFormatterValidator):
|
||||||
def __init__(self, name, value):
|
def __init__(self, name, value):
|
||||||
super().__init__(name, value)
|
super().__init__(name, value)
|
||||||
for key in self._keys:
|
for key in self._keys:
|
||||||
self._value[f"sanitized_{key}"] = sanitize_filename.sanitize(
|
sanitized_key_name = f"sanitized_{key}"
|
||||||
self._value[key]
|
# First, sanitize the format string
|
||||||
|
self._value[sanitized_key_name] = sanitize_filename.sanitize(
|
||||||
|
self._value[key].format_string
|
||||||
|
)
|
||||||
|
|
||||||
|
# Then, convert it into a StringFormatterValidator
|
||||||
|
self._value[sanitized_key_name] = StringFormatterValidator(
|
||||||
|
name="__should_never_fail__",
|
||||||
|
value=self._value[sanitized_key_name],
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue