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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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