protected attributes
This commit is contained in:
parent
459712dcce
commit
ac378ab962
15 changed files with 57 additions and 58 deletions
|
|
@ -108,10 +108,14 @@ class Subscription(object):
|
||||||
custom_root=nfo_options.nfo_root.value,
|
custom_root=nfo_options.nfo_root.value,
|
||||||
attr_type=False,
|
attr_type=False,
|
||||||
)
|
)
|
||||||
nfo_file_path = entry.apply_formatter(
|
|
||||||
|
nfo_file_name = entry.apply_formatter(
|
||||||
format_string=nfo_options.nfo_name.format_string,
|
format_string=nfo_options.nfo_name.format_string,
|
||||||
overrides=self.overrides.dict,
|
overrides=self.overrides.dict,
|
||||||
)
|
)
|
||||||
|
nfo_file_path = Path(self.output_options.output_directory.value) / Path(
|
||||||
|
nfo_file_name
|
||||||
|
)
|
||||||
with open(nfo_file_path, "wb") as f:
|
with open(nfo_file_path, "wb") as f:
|
||||||
f.write(xml)
|
f.write(xml)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,21 +10,21 @@ class StrictDictValidator(DictValidator):
|
||||||
Validates dictionary-based fields with required and optional keys.
|
Validates dictionary-based fields with required and optional keys.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
required_keys: Set[str] = set()
|
_required_keys: Set[str] = set()
|
||||||
optional_keys: Set[str] = set()
|
_optional_keys: Set[str] = set()
|
||||||
allow_extra_keys = False
|
_allow_extra_keys = False
|
||||||
|
|
||||||
def __init__(self, name, value):
|
def __init__(self, name, value):
|
||||||
super().__init__(name, value)
|
super().__init__(name, value)
|
||||||
|
|
||||||
if len(self.allowed_keys) == 0:
|
if len(self._allowed_keys) == 0:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"No required or optional keys defined when using a StrictDictValidator. "
|
"No required or optional keys defined when using a StrictDictValidator. "
|
||||||
"Should be using DictValidator instead."
|
"Should be using DictValidator instead."
|
||||||
)
|
)
|
||||||
|
|
||||||
# Ensure all required keys are present
|
# Ensure all required keys are present
|
||||||
for required_key in self.required_keys:
|
for required_key in self._required_keys:
|
||||||
if required_key not in self.value:
|
if required_key not in self.value:
|
||||||
raise self._validation_exception(
|
raise self._validation_exception(
|
||||||
f"missing the required field '{required_key}'"
|
f"missing the required field '{required_key}'"
|
||||||
|
|
@ -34,24 +34,24 @@ class StrictDictValidator(DictValidator):
|
||||||
if not self.dict:
|
if not self.dict:
|
||||||
raise self._validation_exception(
|
raise self._validation_exception(
|
||||||
f"at least one of the following fields must be defined: "
|
f"at least one of the following fields must be defined: "
|
||||||
f"{', '.join(self.optional_keys)}'"
|
f"{', '.join(self._optional_keys)}'"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Ensure all keys are either required or optional keys if no extra field are allowed
|
# Ensure all keys are either required or optional keys if no extra field are allowed
|
||||||
if not self.allow_extra_keys:
|
if not self._allow_extra_keys:
|
||||||
for object_key in self.keys:
|
for object_key in self.keys:
|
||||||
if object_key not in self.allowed_keys:
|
if object_key not in self._allowed_keys:
|
||||||
error_msg = (
|
error_msg = (
|
||||||
f"'{self.name}' contains the field '{object_key}' which is not allowed. "
|
f"'{self.name}' contains the field '{object_key}' which is not allowed. "
|
||||||
f"Allowed fields: {', '.join(self.allowed_keys)}"
|
f"Allowed fields: {', '.join(self._allowed_keys)}"
|
||||||
)
|
)
|
||||||
raise ValidationException(error_msg)
|
raise ValidationException(error_msg)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def allowed_keys(self) -> List[str]:
|
def _allowed_keys(self) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
Sorted list of required and optional keys
|
Sorted list of required and optional keys
|
||||||
"""
|
"""
|
||||||
return sorted(list(self.required_keys.union(self.optional_keys)))
|
return sorted(list(self._required_keys.union(self._optional_keys)))
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ class StringFormatterValidator(StringValidator):
|
||||||
Ensures user-created formatter strings are valid
|
Ensures user-created formatter strings are valid
|
||||||
"""
|
"""
|
||||||
|
|
||||||
expected_value_type_name = "format string"
|
_expected_value_type_name = "format string"
|
||||||
|
|
||||||
FIELDS_VALIDATOR = re.compile(r"{([a-z_]+?)}")
|
FIELDS_VALIDATOR = re.compile(r"{([a-z_]+?)}")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,12 @@ class StringSelectValidator(StringValidator):
|
||||||
Ensures strings have selected one of the discrete allowed values.
|
Ensures strings have selected one of the discrete allowed values.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
select_values: Set[str] = set()
|
_select_values: Set[str] = set()
|
||||||
|
|
||||||
def __init__(self, name, value: str):
|
def __init__(self, name, value: str):
|
||||||
super().__init__(name=name, value=value)
|
super().__init__(name=name, value=value)
|
||||||
|
|
||||||
if self.value not in self.select_values:
|
if self.value not in self._select_values:
|
||||||
raise self._validation_exception(
|
raise self._validation_exception(
|
||||||
f"Must be one of the following values: {', '.join(self.select_values)}"
|
f"Must be one of the following values: {', '.join(self._select_values)}"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -15,18 +15,18 @@ class Validator:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# If the value is not this expected type, error
|
# If the value is not this expected type, error
|
||||||
expected_value_type: Type = object
|
_expected_value_type: Type = object
|
||||||
|
|
||||||
# When raising an error, call the type this value instead of its python name
|
# When raising an error, call the type this value instead of its python name
|
||||||
expected_value_type_name: Optional[str] = None
|
_expected_value_type_name: Optional[str] = None
|
||||||
|
|
||||||
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 = value
|
||||||
|
|
||||||
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(
|
||||||
self.expected_value_type
|
self._expected_value_type
|
||||||
)
|
)
|
||||||
raise self._validation_exception(
|
raise self._validation_exception(
|
||||||
error_message=f"should be of type {expected_value_type_name}."
|
error_message=f"should be of type {expected_value_type_name}."
|
||||||
|
|
@ -61,8 +61,8 @@ class BoolValidator(Validator):
|
||||||
Validates boolean fields.
|
Validates boolean fields.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
expected_value_type: Type = bool
|
_expected_value_type: Type = bool
|
||||||
expected_value_type_name = "boolean"
|
_expected_value_type_name = "boolean"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> bool:
|
def value(self) -> bool:
|
||||||
|
|
@ -79,8 +79,8 @@ class StringValidator(Validator):
|
||||||
Validates string fields.
|
Validates string fields.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
expected_value_type: Type = str
|
_expected_value_type: Type = str
|
||||||
expected_value_type_name = "string"
|
_expected_value_type_name = "string"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> str:
|
def value(self) -> str:
|
||||||
|
|
@ -101,8 +101,8 @@ class DictValidator(Validator):
|
||||||
a yaml.
|
a yaml.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
expected_value_type = dict
|
_expected_value_type = dict
|
||||||
expected_value_type_name = "object"
|
_expected_value_type_name = "object"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def dict(self) -> dict:
|
def dict(self) -> dict:
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ from ytdl_subscribe.validators.base.validators import StringValidator
|
||||||
|
|
||||||
|
|
||||||
class ConfigValidator(StrictDictValidator):
|
class ConfigValidator(StrictDictValidator):
|
||||||
required_keys = {"working_directory", "presets"}
|
_required_keys = {"working_directory", "presets"}
|
||||||
|
|
||||||
def __init__(self, name: str, value: Any):
|
def __init__(self, name: str, value: Any):
|
||||||
super().__init__(name, value)
|
super().__init__(name, value)
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,12 @@ from ytdl_subscribe.validators.base.validators import StringValidator
|
||||||
|
|
||||||
|
|
||||||
class Id3VersionValidator(StringSelectValidator):
|
class Id3VersionValidator(StringSelectValidator):
|
||||||
select_values = {"2.3", "2.4"}
|
_select_values = {"2.3", "2.4"}
|
||||||
|
|
||||||
|
|
||||||
class Id3Validator(StrictDictValidator):
|
class Id3Validator(StrictDictValidator):
|
||||||
required_keys = {"id3_version", "tags"}
|
_required_keys = {"id3_version", "tags"}
|
||||||
optional_keys = {"multi_value_separator"}
|
_optional_keys = {"multi_value_separator"}
|
||||||
|
|
||||||
def __init__(self, name, value):
|
def __init__(self, name, value):
|
||||||
super().__init__(name, value)
|
super().__init__(name, value)
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,10 @@
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
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 (
|
|
||||||
StringFormatterValidator,
|
|
||||||
)
|
|
||||||
from ytdl_subscribe.validators.config.metadata_options.id3_validator import Id3Validator
|
from ytdl_subscribe.validators.config.metadata_options.id3_validator import Id3Validator
|
||||||
from ytdl_subscribe.validators.config.metadata_options.nfo_validator import NFOValidator
|
from ytdl_subscribe.validators.config.metadata_options.nfo_validator import NFOValidator
|
||||||
|
|
||||||
|
|
||||||
class MetadataOptionsValidator(StrictDictValidator):
|
class MetadataOptionsValidator(StrictDictValidator):
|
||||||
optional_keys = {"id3", "nfo"}
|
_optional_keys = {"id3", "nfo"}
|
||||||
|
|
||||||
def __init__(self, name, value):
|
def __init__(self, name, value):
|
||||||
super().__init__(name, value)
|
super().__init__(name, value)
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,10 @@ from ytdl_subscribe.validators.base.string_formatter_validator import (
|
||||||
from ytdl_subscribe.validators.base.string_formatter_validator import (
|
from ytdl_subscribe.validators.base.string_formatter_validator import (
|
||||||
StringFormatterValidator,
|
StringFormatterValidator,
|
||||||
)
|
)
|
||||||
from ytdl_subscribe.validators.base.string_select_validator import StringSelectValidator
|
|
||||||
from ytdl_subscribe.validators.base.validators import StringValidator
|
|
||||||
|
|
||||||
|
|
||||||
class NFOValidator(StrictDictValidator):
|
class NFOValidator(StrictDictValidator):
|
||||||
required_keys = {"nfo_name", "nfo_root", "tags"}
|
_required_keys = {"nfo_name", "nfo_root", "tags"}
|
||||||
|
|
||||||
def __init__(self, name, value):
|
def __init__(self, name, value):
|
||||||
super().__init__(name, value)
|
super().__init__(name, value)
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,12 @@ from ytdl_subscribe.validators.base.string_select_validator import StringSelectV
|
||||||
|
|
||||||
|
|
||||||
class ConvertThumbnailValidator(StringSelectValidator):
|
class ConvertThumbnailValidator(StringSelectValidator):
|
||||||
select_values = {"jpeg"}
|
_select_values = {"jpeg"}
|
||||||
|
|
||||||
|
|
||||||
class OutputOptionsValidator(StrictDictValidator):
|
class OutputOptionsValidator(StrictDictValidator):
|
||||||
required_keys = {"output_directory", "file_name"}
|
_required_keys = {"output_directory", "file_name"}
|
||||||
optional_keys = {"convert_thumbnail", "thumbnail_name"}
|
_optional_keys = {"convert_thumbnail", "thumbnail_name"}
|
||||||
|
|
||||||
def __init__(self, name, value):
|
def __init__(self, name, value):
|
||||||
super().__init__(name, value)
|
super().__init__(name, value)
|
||||||
|
|
|
||||||
|
|
@ -47,22 +47,22 @@ class OverridesValidator(DictFormatterValidator):
|
||||||
|
|
||||||
|
|
||||||
class PresetValidator(StrictDictValidator):
|
class PresetValidator(StrictDictValidator):
|
||||||
subscription_source_validator_mapping: Dict[str, Type[SourceValidator]] = {
|
_subscription_source_validator_mapping: Dict[str, Type[SourceValidator]] = {
|
||||||
"soundcloud": SoundcloudSourceValidator,
|
"soundcloud": SoundcloudSourceValidator,
|
||||||
"youtube": YoutubeSourceValidator,
|
"youtube": YoutubeSourceValidator,
|
||||||
}
|
}
|
||||||
|
|
||||||
required_keys = {"output_options"}
|
_required_keys = {"output_options"}
|
||||||
optional_keys = {
|
_optional_keys = {
|
||||||
"metadata_options",
|
"metadata_options",
|
||||||
"ytdl_options",
|
"ytdl_options",
|
||||||
"overrides",
|
"overrides",
|
||||||
*subscription_source_validator_mapping.keys(),
|
*_subscription_source_validator_mapping.keys(),
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def available_sources(self) -> List[str]:
|
def available_sources(self) -> List[str]:
|
||||||
return sorted(list(self.subscription_source_validator_mapping.keys()))
|
return sorted(list(self._subscription_source_validator_mapping.keys()))
|
||||||
|
|
||||||
def __validate_and_get_subscription_source(self) -> Tuple[str, SourceValidator]:
|
def __validate_and_get_subscription_source(self) -> Tuple[str, SourceValidator]:
|
||||||
subscription_source: Optional[SourceValidator] = None
|
subscription_source: Optional[SourceValidator] = None
|
||||||
|
|
@ -75,10 +75,10 @@ class PresetValidator(StrictDictValidator):
|
||||||
f"{', '.join(self.available_sources)}"
|
f"{', '.join(self.available_sources)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
if key in self.subscription_source_validator_mapping:
|
if key in self._subscription_source_validator_mapping:
|
||||||
subscription_source_name = key
|
subscription_source_name = key
|
||||||
subscription_source = self.validate_key(
|
subscription_source = self.validate_key(
|
||||||
key=key, validator=self.subscription_source_validator_mapping[key]
|
key=key, validator=self._subscription_source_validator_mapping[key]
|
||||||
)
|
)
|
||||||
|
|
||||||
# If subscription source was not set, error
|
# If subscription source was not set, error
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ from ytdl_subscribe.validators.config.sources.source_validator import SourceVali
|
||||||
|
|
||||||
|
|
||||||
class SoundcloudAlbumsAndSinglesDownloadValidator(DownloadStrategyValidator):
|
class SoundcloudAlbumsAndSinglesDownloadValidator(DownloadStrategyValidator):
|
||||||
required_keys = {"username"}
|
_required_keys = {"username"}
|
||||||
|
|
||||||
def __init__(self, name, value):
|
def __init__(self, name, value):
|
||||||
super().__init__(name, value)
|
super().__init__(name, value)
|
||||||
|
|
@ -15,7 +15,7 @@ class SoundcloudAlbumsAndSinglesDownloadValidator(DownloadStrategyValidator):
|
||||||
|
|
||||||
|
|
||||||
class SoundcloudSourceValidator(SourceValidator):
|
class SoundcloudSourceValidator(SourceValidator):
|
||||||
optional_keys = {"skip_premiere_tracks"}
|
_optional_keys = {"skip_premiere_tracks"}
|
||||||
|
|
||||||
download_strategy_validator_mapping = {
|
download_strategy_validator_mapping = {
|
||||||
"albums_and_singles": SoundcloudAlbumsAndSinglesDownloadValidator
|
"albums_and_singles": SoundcloudAlbumsAndSinglesDownloadValidator
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@ class DownloadStrategyValidator(StrictDictValidator):
|
||||||
|
|
||||||
class SourceValidator(StrictDictValidator):
|
class SourceValidator(StrictDictValidator):
|
||||||
# All media sources must define a download strategy
|
# All media sources must define a download strategy
|
||||||
required_keys = {"download_strategy"}
|
_required_keys = {"download_strategy"}
|
||||||
|
|
||||||
# Extra fields will be strict-validated using other StictDictValidators
|
# Extra fields will be strict-validated using other StictDictValidators
|
||||||
allow_extra_keys = True
|
_allow_extra_keys = True
|
||||||
|
|
||||||
download_strategy_validator_mapping: Dict[str, Type[DownloadStrategyValidator]] = {}
|
download_strategy_validator_mapping: Dict[str, Type[DownloadStrategyValidator]] = {}
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ class SourceValidator(StrictDictValidator):
|
||||||
|
|
||||||
# Remove all non-download strategy keys before passing the dict to the validator
|
# Remove all non-download strategy keys before passing the dict to the validator
|
||||||
download_strategy_dict = copy.deepcopy(self.dict)
|
download_strategy_dict = copy.deepcopy(self.dict)
|
||||||
for key_to_delete in self.allowed_keys:
|
for key_to_delete in self._allowed_keys:
|
||||||
del download_strategy_dict[key_to_delete]
|
del download_strategy_dict[key_to_delete]
|
||||||
|
|
||||||
download_strategy_class = self.download_strategy_validator_mapping[
|
download_strategy_class = self.download_strategy_validator_mapping[
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ from ytdl_subscribe.validators.config.sources.source_validator import SourceVali
|
||||||
|
|
||||||
|
|
||||||
class YoutubePlaylistDownloadValidator(DownloadStrategyValidator):
|
class YoutubePlaylistDownloadValidator(DownloadStrategyValidator):
|
||||||
required_keys = {"playlist_id"}
|
_required_keys = {"playlist_id"}
|
||||||
|
|
||||||
def __init__(self, name, value):
|
def __init__(self, name, value):
|
||||||
super().__init__(name, value)
|
super().__init__(name, value)
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,10 @@ class SubscriptionValidator(StrictDictValidator):
|
||||||
A Subscription is a preset but overrides it with specific values
|
A Subscription is a preset but overrides it with specific values
|
||||||
"""
|
"""
|
||||||
|
|
||||||
required_keys = {"preset"}
|
_required_keys = {"preset"}
|
||||||
optional_keys = PresetValidator.required_keys.union(PresetValidator.optional_keys)
|
_optional_keys = PresetValidator._required_keys.union(
|
||||||
|
PresetValidator._optional_keys
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, config: ConfigValidator, name: str, value: Any):
|
def __init__(self, config: ConfigValidator, name: str, value: Any):
|
||||||
super().__init__(name, value)
|
super().__init__(name, value)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue