update black line-len to 100

This commit is contained in:
jbannon 2022-04-06 07:30:35 +00:00
parent 05737d2b19
commit 2b9ab7c3af
26 changed files with 77 additions and 204 deletions

View file

@ -1,4 +1,7 @@
[tool.isort]
profile = "black"
line_length = 100
force_single_line = true
force_single_line = true
[tool.black]
line_length = 100

View file

@ -18,15 +18,15 @@
# artist: "DeLorra"
# genre: "Synthwave / Electronic"
#
#bl00dwave:
# preset: "soundcloud_with_id3_tags"
# soundcloud:
# username: bl00dwave
# output_options:
# output_directory: "/tmp/bl00dwave"
# overrides:
# artist: "bl00dwave"
# genre: "Synthwave / Electronic"
bl00dwave:
preset: "soundcloud_with_id3_tags"
soundcloud:
username: bl00dwave
output_options:
output_directory: "/tmp/bl00dwave"
overrides:
artist: "bl00dwave"
genre: "Synthwave / Electronic"
tom_petty:
preset: "music_videos"

View file

@ -1,9 +1,7 @@
import pytest
from ytdl_subscribe.entries.entry import Entry
from ytdl_subscribe.validators.base.string_formatter_validators import (
StringFormatterValidator,
)
from ytdl_subscribe.validators.base.string_formatter_validators import StringFormatterValidator
@pytest.fixture
@ -47,9 +45,7 @@ def download_file_name(uid, ext):
@pytest.fixture
def mock_entry_to_dict(
uid, title, ext, upload_date, upload_year, thumbnail, thumbnail_ext
):
def mock_entry_to_dict(uid, title, ext, upload_date, upload_year, thumbnail, thumbnail_ext):
return {
"uid": uid,
"title": title,
@ -114,9 +110,7 @@ def validate_entry_dict_contains_valid_formatters():
format_string = f"test {{{key}}} formatting works"
assert (
entry.apply_formatter(
StringFormatterValidator(name="test", value=format_string)
)
entry.apply_formatter(StringFormatterValidator(name="test", value=format_string))
== expected_string
)

View file

@ -2,12 +2,8 @@ import tempfile
import pytest
from ytdl_subscribe.validators.base.string_formatter_validators import (
StringFormatterValidator,
)
from ytdl_subscribe.validators.config.overrides.overrides_validator import (
OverridesValidator,
)
from ytdl_subscribe.validators.base.string_formatter_validators import StringFormatterValidator
from ytdl_subscribe.validators.config.overrides.overrides_validator import OverridesValidator
from ytdl_subscribe.validators.exceptions import StringFormattingException
from ytdl_subscribe.validators.exceptions import ValidationException
@ -47,9 +43,7 @@ class TestEntry(object):
mock_entry.kwargs(key)
def test_entry_formatter_fails_missing_field(self, mock_entry):
format_string = StringFormatterValidator(
name="test", value=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()))
expected_error_msg = (
f"Validation error in test: Format variable 'bah_humbug' does not exist. "

View file

@ -8,9 +8,7 @@ from ytdl_subscribe.validators.exceptions import ValidationException
class TestDictValidator:
@pytest.mark.parametrize(
"value", [{}, {"key": "value"}, {"b": {}, "a": "keys_out_of_order"}]
)
@pytest.mark.parametrize("value", [{}, {"key": "value"}, {"b": {}, "a": "keys_out_of_order"}])
def test_dict_validator(self, value):
dict_validator = DictValidator(name="good_dict_validator", value=value)
assert dict_validator._name == "good_dict_validator"
@ -31,9 +29,7 @@ class TestDictValidator:
)
def test_dict_validator_validate_key(self, value, validator_class):
dict_validator = DictValidator(name="validate_key", value={"key_name": value})
validated_key = dict_validator._validate_key(
key="key_name", validator=validator_class
)
validated_key = dict_validator._validate_key(key="key_name", validator=validator_class)
assert isinstance(validated_key, validator_class)
assert validated_key.value == value
@ -95,9 +91,7 @@ class TestDictValidator:
class TestLiteralDictValidator:
@pytest.mark.parametrize(
"value", [{}, {"key": "value"}, {"b": {}, "a": "keys_out_of_order"}]
)
@pytest.mark.parametrize("value", [{}, {"key": "value"}, {"b": {}, "a": "keys_out_of_order"}])
def test_literal_dict_validator_dict_and_keys(self, value):
dict_validator = LiteralDictValidator(name="good_dict_validator", value=value)
assert dict_validator._name == "good_dict_validator"

View file

@ -1,11 +1,7 @@
import pytest
from ytdl_subscribe.validators.base.string_formatter_validators import (
DictFormatterValidator,
)
from ytdl_subscribe.validators.base.string_formatter_validators import (
StringFormatterValidator,
)
from ytdl_subscribe.validators.base.string_formatter_validators import DictFormatterValidator
from ytdl_subscribe.validators.base.string_formatter_validators import StringFormatterValidator
from ytdl_subscribe.validators.exceptions import StringFormattingException
from ytdl_subscribe.validators.exceptions import ValidationException
@ -29,9 +25,7 @@ def error_message_unequal_regex_matches_str():
class TestStringFormatterValidator(object):
def test_parse(self):
format_string = "Here is my {var_one} and {var_two} 💩"
validator = StringFormatterValidator(
name="test_format_variables", value=format_string
)
validator = StringFormatterValidator(name="test_format_variables", value=format_string)
assert validator.format_string == format_string
assert validator.format_variables == ["var_one", "var_two"]
@ -54,12 +48,8 @@ class TestStringFormatterValidator(object):
"Try }var_one} and {var_one}",
],
)
def test_validate_fail_uneven_brackets(
self, format_string, error_message_unequal_brackets_str
):
expected_error_msg = (
f"Validation error in fail: {error_message_unequal_brackets_str}"
)
def test_validate_fail_uneven_brackets(self, format_string, error_message_unequal_brackets_str):
expected_error_msg = f"Validation error in fail: {error_message_unequal_brackets_str}"
with pytest.raises(ValidationException, match=expected_error_msg):
_ = StringFormatterValidator(name="fail", value=format_string)
@ -78,9 +68,7 @@ class TestStringFormatterValidator(object):
def test_validate_fail_bad_variable(
self, format_string, error_message_unequal_regex_matches_str
):
expected_error_msg = (
f"Validation error in fail: {error_message_unequal_regex_matches_str}"
)
expected_error_msg = f"Validation error in fail: {error_message_unequal_regex_matches_str}"
with pytest.raises(ValidationException, match=expected_error_msg):
_ = StringFormatterValidator(name="fail", value=format_string)
@ -92,9 +80,7 @@ class TestStringFormatterValidator(object):
("{try} {valid_var}", "try"),
],
)
def test_validate_fail_variable_keyword_or_not_identifier(
self, format_string, bad_variable
):
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."
@ -105,14 +91,10 @@ class TestStringFormatterValidator(object):
def test_string_formatter_single_field(self):
uid = "this uid"
format_string = StringFormatterValidator(
name="test", value=f"prefix {{uid}} suffix"
)
format_string = StringFormatterValidator(name="test", value=f"prefix {{uid}} suffix")
expected_string = f"prefix {uid} suffix"
assert (
format_string.apply_formatter(variable_dict={"uid": uid}) == expected_string
)
assert format_string.apply_formatter(variable_dict={"uid": uid}) == expected_string
def test_entry_formatter_duplicate_fields(self):
upload_year = "2022"
@ -133,15 +115,10 @@ class TestStringFormatterValidator(object):
"level_c": "level c and {level_b}",
}
format_string = StringFormatterValidator(
name="test", value="level d and {level_c}"
)
format_string = StringFormatterValidator(name="test", value="level d and {level_c}")
expected_string = "level d and level c and level b and level a"
assert (
format_string.apply_formatter(variable_dict=variable_dict)
== expected_string
)
assert format_string.apply_formatter(variable_dict=variable_dict) == expected_string
def test_entry_formatter_override_recursive_fail_cycle(self):
variable_dict = {

View file

@ -24,9 +24,7 @@ class Downloader:
return {}
@classmethod
def _configure_ytdl_options(
cls, ytdl_options: Optional[Dict], working_directory: str
) -> Dict:
def _configure_ytdl_options(cls, ytdl_options: Optional[Dict], working_directory: str) -> Dict:
"""Configure the ytdl options for the downloader"""
if ytdl_options is None:
ytdl_options = {}
@ -56,9 +54,7 @@ class Downloader:
)
@contextmanager
def ytdl_downloader(
self, ytdl_options_overrides: Optional[Dict] = None
) -> ytdl.YoutubeDL:
def ytdl_downloader(self, ytdl_options_overrides: Optional[Dict] = None) -> ytdl.YoutubeDL:
"""
Context manager to interact with yt_dlp.
"""
@ -69,9 +65,7 @@ class Downloader:
with ytdl.YoutubeDL(ytdl_options) as ytdl_downloader:
yield ytdl_downloader
def extract_info(
self, ytdl_options_overrides: Optional[Dict] = None, **kwargs
) -> Dict:
def extract_info(self, ytdl_options_overrides: Optional[Dict] = None, **kwargs) -> Dict:
"""
Wrapper around yt_dlp.YoutubeDL.YoutubeDL.extract_info
All kwargs will passed to the extract_info function.

View file

@ -25,9 +25,7 @@ class YoutubeDownloader(Downloader):
not fetch the metadata (maybe there is a way??)
"""
ytdl_metadata_override = {
"download_archive": str(
Path(self.output_directory) / "ytdl-download-archive.txt"
),
"download_archive": str(Path(self.output_directory) / "ytdl-download-archive.txt"),
"writeinfojson": True,
}
_ = self.extract_info(ytdl_options_overrides=ytdl_metadata_override, url=url)
@ -45,12 +43,8 @@ class YoutubeDownloader(Downloader):
# Load the entries from info.json, ignore the playlist entry
for file_name in os.listdir(self.output_directory):
if file_name.endswith(".info.json") and not file_name.startswith(
playlist_id
):
with open(
Path(self.output_directory) / file_name, "r", encoding="utf-8"
) as file:
if file_name.endswith(".info.json") and not file_name.startswith(playlist_id):
with open(Path(self.output_directory) / file_name, "r", encoding="utf-8") as file:
entries.append(YoutubeVideo(**json.load(file)))
return entries

View file

@ -6,12 +6,8 @@ from typing import Optional
from sanitize_filename import sanitize
from ytdl_subscribe.validators.base.string_formatter_validators import (
StringFormatterValidator,
)
from ytdl_subscribe.validators.config.overrides.overrides_validator import (
OverridesValidator,
)
from ytdl_subscribe.validators.base.string_formatter_validators import StringFormatterValidator
from ytdl_subscribe.validators.config.overrides.overrides_validator import OverridesValidator
from ytdl_subscribe.validators.exceptions import ValidationException
@ -33,9 +29,7 @@ class Entry:
def kwargs(self, key) -> Any:
"""Returns an internal kwarg value supplied from ytdl"""
if not self.kwargs_contains(key):
raise KeyError(
f"Expected '{key}' in {self.__class__.__name__} but does not exist."
)
raise KeyError(f"Expected '{key}' in {self.__class__.__name__} but does not exist.")
return self._kwargs[key]
@property

View file

@ -103,9 +103,7 @@ class SoundcloudAlbum(Entry):
"""
return [SoundcloudTrack(**entry) for entry in self.kwargs("entries")]
def album_tracks(
self, skip_premiere_tracks: bool = True
) -> List[SoundcloudAlbumTrack]:
def album_tracks(self, skip_premiere_tracks: bool = True) -> List[SoundcloudAlbumTrack]:
"""
Returns all tracks in the album represented as album-tracks. They will share the
same album name, have ordered track numbers, and a shared album year.

View file

@ -5,9 +5,7 @@ from typing import List
###################################################################################################
# GLOBAL PARSER
from ytdl_subscribe.validators.config.config_file_validator import ConfigFileValidator
from ytdl_subscribe.validators.config.subscription_validator import (
SubscriptionValidator,
)
from ytdl_subscribe.validators.config.subscription_validator import SubscriptionValidator
parser = argparse.ArgumentParser(
description="YoutubeDL-Subscribe: Download and organize your favorite media hassle-free."

View file

@ -53,9 +53,7 @@ class SoundcloudAlbumsAndSinglesSubscription(SoundcloudSubscription):
artist_name=self.download_strategy_options.username.value
)
tracks += [
track
for track in single_tracks
if not any(album.contains(track) for album in albums)
track for track in single_tracks if not any(album.contains(track) for album in albums)
]
for entry in tracks:

View file

@ -10,9 +10,7 @@ from PIL import Image
from ytdl_subscribe.downloaders.downloader import Downloader
from ytdl_subscribe.entries.entry import Entry
from ytdl_subscribe.validators.base.string_formatter_validators import (
StringFormatterValidator,
)
from ytdl_subscribe.validators.base.string_formatter_validators import StringFormatterValidator
from ytdl_subscribe.validators.config.config_options.config_options_validator import (
ConfigOptionsValidator,
)
@ -20,9 +18,7 @@ from ytdl_subscribe.validators.config.preset_validator import PresetValidator
from ytdl_subscribe.validators.config.source_options.source_validator import (
DownloadStrategyValidator,
)
from ytdl_subscribe.validators.config.source_options.source_validator import (
SourceValidator,
)
from ytdl_subscribe.validators.config.source_options.source_validator import SourceValidator
SOURCE_T = TypeVar("SOURCE_T", bound=SourceValidator)
DOWNLOAD_STRATEGY_T = TypeVar("DOWNLOAD_STRATEGY_T", bound=DownloadStrategyValidator)
@ -83,9 +79,7 @@ class Subscription(object):
ytdl_options=self.ytdl_options.dict,
)
def _apply_formatter(
self, entry: Entry, formatter: StringFormatterValidator
) -> str:
def _apply_formatter(self, entry: Entry, formatter: StringFormatterValidator) -> str:
"""
Parameters
----------
@ -103,13 +97,9 @@ class Subscription(object):
def _post_process_tagging(self, entry: Entry):
id3_options = self.metadata_options.id3
audio_file = music_tag.load_file(
entry.file_path(relative_directory=self.working_directory)
)
audio_file = music_tag.load_file(entry.file_path(relative_directory=self.working_directory))
for tag, tag_formatter in id3_options.tags.dict.items():
audio_file[tag] = self._apply_formatter(
entry=entry, formatter=tag_formatter
)
audio_file[tag] = self._apply_formatter(entry=entry, formatter=tag_formatter)
audio_file.save()
def _post_process_nfo(self, entry):
@ -128,9 +118,7 @@ class Subscription(object):
attr_type=False,
)
nfo_file_name = self._apply_formatter(
entry=entry, formatter=nfo_options.nfo_name
)
nfo_file_name = self._apply_formatter(entry=entry, formatter=nfo_options.nfo_name)
output_directory = self._apply_formatter(
entry=entry, formatter=self.output_options.output_directory
)
@ -151,9 +139,7 @@ class Subscription(object):
self._post_process_tagging(entry)
# Move the file after all direct file modifications are complete
entry_source_file_path = entry.file_path(
relative_directory=self.working_directory
)
entry_source_file_path = entry.file_path(relative_directory=self.working_directory)
output_directory = self._apply_formatter(
entry=entry, formatter=self.output_options.output_directory
@ -169,9 +155,7 @@ class Subscription(object):
# Download the thumbnail if its present
if self.output_options.thumbnail_name:
source_thumbnail_path = entry.thumbnail_path(
relative_directory=self.working_directory
)
source_thumbnail_path = entry.thumbnail_path(relative_directory=self.working_directory)
output_thumbnail_name = self._apply_formatter(
entry=entry, formatter=self.output_options.thumbnail_name

View file

@ -26,9 +26,7 @@ class StrictDictValidator(DictValidator):
# Ensure all required keys are present
for required_key in self._required_keys:
if required_key not in self._dict:
raise self._validation_exception(
f"missing the required field '{required_key}'"
)
raise self._validation_exception(f"missing the required field '{required_key}'")
# Ensure an empty dict was not passed as the value
if not self._dict:

View file

@ -122,9 +122,7 @@ class DictFormatterValidator(LiteralDictValidator):
super().__init__(name, value)
for key in self._keys:
self._value[key] = self._validate_key(
key=key, validator=StringFormatterValidator
)
self._value[key] = self._validate_key(key=key, validator=StringFormatterValidator)
@property
def dict(self) -> Dict[str, StringFormatterValidator]:
@ -134,7 +132,4 @@ class DictFormatterValidator(LiteralDictValidator):
@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()
}
return {key: string_formatter.format_string for key, string_formatter in self.dict.items()}

View file

@ -28,9 +28,7 @@ class Validator(ABC):
def __init__(self, name: str, value: Any):
self._name = name
self._value = copy.deepcopy(
value
) # Always deep copy to avoid editing references
self._value = copy.deepcopy(value) # Always deep copy to avoid editing references
if not isinstance(self._value, self._expected_value_type):
expected_value_type_name = self._expected_value_type_name or str(
@ -147,9 +145,7 @@ class DictValidator(Validator):
An instance of the specified validator
"""
if key not in self._dict and default is None:
raise self._validation_exception(
f"{key} is missing when it should be present."
)
raise self._validation_exception(f"{key} is missing when it should be present.")
return validator(
name=f"{self._name}.{key}",

View file

@ -18,9 +18,7 @@ class ConfigFileValidator(StrictDictValidator):
def __init__(self, name: str, value: Any):
super().__init__(name, value)
self.config_options = self._validate_key(
"configuration", ConfigOptionsValidator
)
self.config_options = self._validate_key("configuration", ConfigOptionsValidator)
self.presets = self._validate_key("presets", ConfigPresetsValidator)
@classmethod

View file

@ -1,7 +1,5 @@
from ytdl_subscribe.validators.base.strict_dict_validator import StrictDictValidator
from ytdl_subscribe.validators.base.string_formatter_validators import (
DictFormatterValidator,
)
from ytdl_subscribe.validators.base.string_formatter_validators import DictFormatterValidator
from ytdl_subscribe.validators.base.string_select_validator import StringSelectValidator
from ytdl_subscribe.validators.base.validators import StringValidator

View file

@ -1,10 +1,6 @@
from ytdl_subscribe.validators.base.strict_dict_validator import StrictDictValidator
from ytdl_subscribe.validators.base.string_formatter_validators import (
DictFormatterValidator,
)
from ytdl_subscribe.validators.base.string_formatter_validators import (
StringFormatterValidator,
)
from ytdl_subscribe.validators.base.string_formatter_validators import DictFormatterValidator
from ytdl_subscribe.validators.base.string_formatter_validators import StringFormatterValidator
class NFOValidator(StrictDictValidator):
@ -13,10 +9,6 @@ class NFOValidator(StrictDictValidator):
def __init__(self, name, value):
super().__init__(name, value)
self.nfo_name = self._validate_key(
key="nfo_name", validator=StringFormatterValidator
)
self.nfo_root = self._validate_key(
key="nfo_root", validator=StringFormatterValidator
)
self.nfo_name = self._validate_key(key="nfo_name", validator=StringFormatterValidator)
self.nfo_root = self._validate_key(key="nfo_root", validator=StringFormatterValidator)
self.tags = self._validate_key(key="tags", validator=DictFormatterValidator)

View file

@ -1,7 +1,5 @@
from ytdl_subscribe.validators.base.strict_dict_validator import StrictDictValidator
from ytdl_subscribe.validators.base.string_formatter_validators import (
StringFormatterValidator,
)
from ytdl_subscribe.validators.base.string_formatter_validators import StringFormatterValidator
from ytdl_subscribe.validators.base.string_select_validator import StringSelectValidator

View file

@ -1,11 +1,7 @@
import sanitize_filename
from ytdl_subscribe.validators.base.string_formatter_validators import (
DictFormatterValidator,
)
from ytdl_subscribe.validators.base.string_formatter_validators import (
StringFormatterValidator,
)
from ytdl_subscribe.validators.base.string_formatter_validators import DictFormatterValidator
from ytdl_subscribe.validators.base.string_formatter_validators import StringFormatterValidator
class OverridesValidator(DictFormatterValidator):

View file

@ -11,15 +11,11 @@ from ytdl_subscribe.validators.config.metadata_options.metadata_options_validato
from ytdl_subscribe.validators.config.output_options.output_options_validator import (
OutputOptionsValidator,
)
from ytdl_subscribe.validators.config.overrides.overrides_validator import (
OverridesValidator,
)
from ytdl_subscribe.validators.config.overrides.overrides_validator import OverridesValidator
from ytdl_subscribe.validators.config.source_options.soundcloud_validators import (
SoundcloudSourceValidator,
)
from ytdl_subscribe.validators.config.source_options.source_validator import (
SourceValidator,
)
from ytdl_subscribe.validators.config.source_options.source_validator import SourceValidator
from ytdl_subscribe.validators.config.source_options.youtube_validators import (
YoutubeSourceValidator,
)

View file

@ -3,9 +3,7 @@ from ytdl_subscribe.validators.base.validators import StringValidator
from ytdl_subscribe.validators.config.source_options.source_validator import (
DownloadStrategyValidator,
)
from ytdl_subscribe.validators.config.source_options.source_validator import (
SourceValidator,
)
from ytdl_subscribe.validators.config.source_options.source_validator import SourceValidator
class SoundcloudAlbumsAndSinglesDownloadValidator(DownloadStrategyValidator):

View file

@ -18,9 +18,7 @@ class SourceValidator(StrictDictValidator):
# Extra fields will be strict-validated using other StictDictValidators
_allow_extra_keys = True
_download_strategy_validator_mapping: Dict[
str, Type[DownloadStrategyValidator]
] = {}
_download_strategy_validator_mapping: Dict[str, Type[DownloadStrategyValidator]] = {}
def __init__(self, name: str, value: Any):
super().__init__(name=name, value=value)
@ -39,9 +37,7 @@ class SourceValidator(StrictDictValidator):
for key_to_delete in self._allowed_keys:
del download_strategy_dict[key_to_delete]
download_strategy_class = self._download_strategy_validator_mapping[
download_strategy_name
]
download_strategy_class = self._download_strategy_validator_mapping[download_strategy_name]
self.download_strategy = download_strategy_class(
name=self._name, value=download_strategy_dict
)

View file

@ -4,9 +4,7 @@ from ytdl_subscribe.validators.base.validators import StringValidator
from ytdl_subscribe.validators.config.source_options.source_validator import (
DownloadStrategyValidator,
)
from ytdl_subscribe.validators.config.source_options.source_validator import (
SourceValidator,
)
from ytdl_subscribe.validators.config.source_options.source_validator import SourceValidator
class YoutubePlaylistDownloadValidator(DownloadStrategyValidator):
@ -18,9 +16,7 @@ class YoutubePlaylistDownloadValidator(DownloadStrategyValidator):
class YoutubeSourceValidator(SourceValidator):
_download_strategy_validator_mapping = {
"playlist": YoutubePlaylistDownloadValidator
}
_download_strategy_validator_mapping = {"playlist": YoutubePlaylistDownloadValidator}
def __init__(self, name: str, value: Any):
super().__init__(name=name, value=value)

View file

@ -5,17 +5,13 @@ from typing import List
import yaml
from mergedeep import mergedeep
from ytdl_subscribe.subscriptions.soundcloud import (
SoundcloudAlbumsAndSinglesSubscription,
)
from ytdl_subscribe.subscriptions.soundcloud import SoundcloudAlbumsAndSinglesSubscription
from ytdl_subscribe.subscriptions.subscription import Subscription
from ytdl_subscribe.subscriptions.youtube import YoutubePlaylistSubscription
from ytdl_subscribe.validators.base.strict_dict_validator import StrictDictValidator
from ytdl_subscribe.validators.base.validators import StringValidator
from ytdl_subscribe.validators.config.config_file_validator import ConfigFileValidator
from ytdl_subscribe.validators.config.overrides.overrides_validator import (
OverridesValidator,
)
from ytdl_subscribe.validators.config.overrides.overrides_validator import OverridesValidator
from ytdl_subscribe.validators.config.preset_validator import PRESET_OPTIONAL_KEYS
from ytdl_subscribe.validators.config.preset_validator import PRESET_REQUIRED_KEYS
from ytdl_subscribe.validators.config.preset_validator import PresetValidator
@ -60,9 +56,7 @@ class SubscriptionValidator(StrictDictValidator):
# A little hacky, we will override the preset with the contents of this subscription,
# then validate it
preset_dict = copy.deepcopy(self.config.presets.dict[preset_name])
preset_dict = mergedeep.merge(
preset_dict, self._dict, strategy=mergedeep.Strategy.REPLACE
)
preset_dict = mergedeep.merge(preset_dict, self._dict, strategy=mergedeep.Strategy.REPLACE)
del preset_dict["preset"]
self.preset = PresetValidator(