protected attributes

This commit is contained in:
jbannon 2022-04-04 23:35:37 +00:00
parent 459712dcce
commit ac378ab962
15 changed files with 57 additions and 58 deletions

View file

@ -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)

View file

@ -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)))

View file

@ -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_]+?)}")

View file

@ -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)}"
)

View file

@ -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:

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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[

View file

@ -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)

View file

@ -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)