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,
|
||||
attr_type=False,
|
||||
)
|
||||
nfo_file_path = entry.apply_formatter(
|
||||
|
||||
nfo_file_name = entry.apply_formatter(
|
||||
format_string=nfo_options.nfo_name.format_string,
|
||||
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:
|
||||
f.write(xml)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,21 +10,21 @@ class StrictDictValidator(DictValidator):
|
|||
Validates dictionary-based fields with required and optional keys.
|
||||
"""
|
||||
|
||||
required_keys: Set[str] = set()
|
||||
optional_keys: Set[str] = set()
|
||||
allow_extra_keys = False
|
||||
_required_keys: Set[str] = set()
|
||||
_optional_keys: Set[str] = set()
|
||||
_allow_extra_keys = False
|
||||
|
||||
def __init__(self, name, value):
|
||||
super().__init__(name, value)
|
||||
|
||||
if len(self.allowed_keys) == 0:
|
||||
if len(self._allowed_keys) == 0:
|
||||
raise ValueError(
|
||||
"No required or optional keys defined when using a StrictDictValidator. "
|
||||
"Should be using DictValidator instead."
|
||||
)
|
||||
|
||||
# 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:
|
||||
raise self._validation_exception(
|
||||
f"missing the required field '{required_key}'"
|
||||
|
|
@ -34,24 +34,24 @@ class StrictDictValidator(DictValidator):
|
|||
if not self.dict:
|
||||
raise self._validation_exception(
|
||||
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
|
||||
if not self.allow_extra_keys:
|
||||
if not self._allow_extra_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 = (
|
||||
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)
|
||||
|
||||
@property
|
||||
def allowed_keys(self) -> List[str]:
|
||||
def _allowed_keys(self) -> List[str]:
|
||||
"""
|
||||
Returns
|
||||
-------
|
||||
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
|
||||
"""
|
||||
|
||||
expected_value_type_name = "format string"
|
||||
_expected_value_type_name = "format string"
|
||||
|
||||
FIELDS_VALIDATOR = re.compile(r"{([a-z_]+?)}")
|
||||
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@ class StringSelectValidator(StringValidator):
|
|||
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):
|
||||
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(
|
||||
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
|
||||
expected_value_type: Type = object
|
||||
_expected_value_type: Type = object
|
||||
|
||||
# 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):
|
||||
self.name = name
|
||||
self._value = value
|
||||
|
||||
if not isinstance(self._value, self.expected_value_type):
|
||||
expected_value_type_name = self.expected_value_type_name or str(
|
||||
self.expected_value_type
|
||||
if not isinstance(self._value, self._expected_value_type):
|
||||
expected_value_type_name = self._expected_value_type_name or str(
|
||||
self._expected_value_type
|
||||
)
|
||||
raise self._validation_exception(
|
||||
error_message=f"should be of type {expected_value_type_name}."
|
||||
|
|
@ -61,8 +61,8 @@ class BoolValidator(Validator):
|
|||
Validates boolean fields.
|
||||
"""
|
||||
|
||||
expected_value_type: Type = bool
|
||||
expected_value_type_name = "boolean"
|
||||
_expected_value_type: Type = bool
|
||||
_expected_value_type_name = "boolean"
|
||||
|
||||
@property
|
||||
def value(self) -> bool:
|
||||
|
|
@ -79,8 +79,8 @@ class StringValidator(Validator):
|
|||
Validates string fields.
|
||||
"""
|
||||
|
||||
expected_value_type: Type = str
|
||||
expected_value_type_name = "string"
|
||||
_expected_value_type: Type = str
|
||||
_expected_value_type_name = "string"
|
||||
|
||||
@property
|
||||
def value(self) -> str:
|
||||
|
|
@ -101,8 +101,8 @@ class DictValidator(Validator):
|
|||
a yaml.
|
||||
"""
|
||||
|
||||
expected_value_type = dict
|
||||
expected_value_type_name = "object"
|
||||
_expected_value_type = dict
|
||||
_expected_value_type_name = "object"
|
||||
|
||||
@property
|
||||
def dict(self) -> dict:
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from ytdl_subscribe.validators.base.validators import StringValidator
|
|||
|
||||
|
||||
class ConfigValidator(StrictDictValidator):
|
||||
required_keys = {"working_directory", "presets"}
|
||||
_required_keys = {"working_directory", "presets"}
|
||||
|
||||
def __init__(self, name: str, value: Any):
|
||||
super().__init__(name, value)
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ from ytdl_subscribe.validators.base.validators import StringValidator
|
|||
|
||||
|
||||
class Id3VersionValidator(StringSelectValidator):
|
||||
select_values = {"2.3", "2.4"}
|
||||
_select_values = {"2.3", "2.4"}
|
||||
|
||||
|
||||
class Id3Validator(StrictDictValidator):
|
||||
required_keys = {"id3_version", "tags"}
|
||||
optional_keys = {"multi_value_separator"}
|
||||
_required_keys = {"id3_version", "tags"}
|
||||
_optional_keys = {"multi_value_separator"}
|
||||
|
||||
def __init__(self, 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.string_formatter_validator import (
|
||||
StringFormatterValidator,
|
||||
)
|
||||
from ytdl_subscribe.validators.config.metadata_options.id3_validator import Id3Validator
|
||||
from ytdl_subscribe.validators.config.metadata_options.nfo_validator import NFOValidator
|
||||
|
||||
|
||||
class MetadataOptionsValidator(StrictDictValidator):
|
||||
optional_keys = {"id3", "nfo"}
|
||||
_optional_keys = {"id3", "nfo"}
|
||||
|
||||
def __init__(self, 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 (
|
||||
StringFormatterValidator,
|
||||
)
|
||||
from ytdl_subscribe.validators.base.string_select_validator import StringSelectValidator
|
||||
from ytdl_subscribe.validators.base.validators import StringValidator
|
||||
|
||||
|
||||
class NFOValidator(StrictDictValidator):
|
||||
required_keys = {"nfo_name", "nfo_root", "tags"}
|
||||
_required_keys = {"nfo_name", "nfo_root", "tags"}
|
||||
|
||||
def __init__(self, name, value):
|
||||
super().__init__(name, value)
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ from ytdl_subscribe.validators.base.string_select_validator import StringSelectV
|
|||
|
||||
|
||||
class ConvertThumbnailValidator(StringSelectValidator):
|
||||
select_values = {"jpeg"}
|
||||
_select_values = {"jpeg"}
|
||||
|
||||
|
||||
class OutputOptionsValidator(StrictDictValidator):
|
||||
required_keys = {"output_directory", "file_name"}
|
||||
optional_keys = {"convert_thumbnail", "thumbnail_name"}
|
||||
_required_keys = {"output_directory", "file_name"}
|
||||
_optional_keys = {"convert_thumbnail", "thumbnail_name"}
|
||||
|
||||
def __init__(self, name, value):
|
||||
super().__init__(name, value)
|
||||
|
|
|
|||
|
|
@ -47,22 +47,22 @@ class OverridesValidator(DictFormatterValidator):
|
|||
|
||||
|
||||
class PresetValidator(StrictDictValidator):
|
||||
subscription_source_validator_mapping: Dict[str, Type[SourceValidator]] = {
|
||||
_subscription_source_validator_mapping: Dict[str, Type[SourceValidator]] = {
|
||||
"soundcloud": SoundcloudSourceValidator,
|
||||
"youtube": YoutubeSourceValidator,
|
||||
}
|
||||
|
||||
required_keys = {"output_options"}
|
||||
optional_keys = {
|
||||
_required_keys = {"output_options"}
|
||||
_optional_keys = {
|
||||
"metadata_options",
|
||||
"ytdl_options",
|
||||
"overrides",
|
||||
*subscription_source_validator_mapping.keys(),
|
||||
*_subscription_source_validator_mapping.keys(),
|
||||
}
|
||||
|
||||
@property
|
||||
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]:
|
||||
subscription_source: Optional[SourceValidator] = None
|
||||
|
|
@ -75,10 +75,10 @@ class PresetValidator(StrictDictValidator):
|
|||
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 = 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
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from ytdl_subscribe.validators.config.sources.source_validator import SourceVali
|
|||
|
||||
|
||||
class SoundcloudAlbumsAndSinglesDownloadValidator(DownloadStrategyValidator):
|
||||
required_keys = {"username"}
|
||||
_required_keys = {"username"}
|
||||
|
||||
def __init__(self, name, value):
|
||||
super().__init__(name, value)
|
||||
|
|
@ -15,7 +15,7 @@ class SoundcloudAlbumsAndSinglesDownloadValidator(DownloadStrategyValidator):
|
|||
|
||||
|
||||
class SoundcloudSourceValidator(SourceValidator):
|
||||
optional_keys = {"skip_premiere_tracks"}
|
||||
_optional_keys = {"skip_premiere_tracks"}
|
||||
|
||||
download_strategy_validator_mapping = {
|
||||
"albums_and_singles": SoundcloudAlbumsAndSinglesDownloadValidator
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@ class DownloadStrategyValidator(StrictDictValidator):
|
|||
|
||||
class SourceValidator(StrictDictValidator):
|
||||
# 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
|
||||
allow_extra_keys = True
|
||||
_allow_extra_keys = True
|
||||
|
||||
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
|
||||
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]
|
||||
|
||||
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):
|
||||
required_keys = {"playlist_id"}
|
||||
_required_keys = {"playlist_id"}
|
||||
|
||||
def __init__(self, name, value):
|
||||
super().__init__(name, value)
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@ class SubscriptionValidator(StrictDictValidator):
|
|||
A Subscription is a preset but overrides it with specific values
|
||||
"""
|
||||
|
||||
required_keys = {"preset"}
|
||||
optional_keys = PresetValidator.required_keys.union(PresetValidator.optional_keys)
|
||||
_required_keys = {"preset"}
|
||||
_optional_keys = PresetValidator._required_keys.union(
|
||||
PresetValidator._optional_keys
|
||||
)
|
||||
|
||||
def __init__(self, config: ConfigValidator, name: str, value: Any):
|
||||
super().__init__(name, value)
|
||||
|
|
|
|||
Loading…
Reference in a new issue