docstrings, simplify dict validator

This commit is contained in:
jbannon 2022-04-03 18:29:34 +00:00
parent 3eca67101b
commit 16cba13570
2 changed files with 80 additions and 25 deletions

View file

@ -1,4 +1,5 @@
from typing import Any
from typing import List
from typing import Optional
from typing import Type
from typing import TypeVar
@ -7,18 +8,20 @@ from ytdl_subscribe.validators.exceptions import ValidationException
class Validator:
"""
Abstract class used to validate any kind of field. Will ensure the value is the specified type.
"""
# The python type that value should be
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
def __validate_value(self):
"""
Returns
-------
Validation exception to raise when the value's type is not the expected type
"""
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
@ -27,36 +30,63 @@ class Validator:
error_message=f"should be of type {expected_value_type_name}."
)
def __init__(self, name: str, value: Any):
self.name = name
self._value = value
self.__validate_value()
@property
def value(self) -> object:
"""
Returns
-------
Value of the validator
"""
return self._value
def _validation_exception(self, error_message: str):
def _validation_exception(self, error_message: str) -> ValidationException:
"""
Parameters
----------
error_message
Error message to include in the ValidationException
Returns
-------
Validation exception with a consistent prefix.
"""
prefix = f"Validation error in {self.name}: "
return ValidationException(f"{prefix}{error_message}")
class BoolValidator(Validator):
"""
Validates boolean fields.
"""
expected_value_type: Type = bool
expected_value_type_name = "boolean"
@property
def value(self) -> bool:
"""
Returns
-------
Boolean value
"""
return self._value
class StringValidator(Validator):
"""
Validates string fields.
"""
expected_value_type: Type = str
expected_value_type_name = "string"
@property
def value(self) -> str:
"""
Returns
-------
String value
"""
return self._value
@ -64,24 +94,49 @@ T = TypeVar("T", bound=Validator)
class DictValidator(Validator):
"""
Validates dictionary-based fields. Errors to them as 'object's since this could be validating a yaml.
"""
expected_value_type = dict
expected_value_type_name = "object" # for non-python users
expected_value_type_name = "object"
@property
def dict(self) -> dict:
"""
Returns
-------
Dictionary value
"""
return self._value
@property
def keys(self):
def keys(self) -> List[str]:
"""
Returns
-------
Sorted list of dictionary keys
"""
return sorted(list(self.dict.keys()))
def get(self, key: str, default: Optional[Any] = None) -> Any:
return self.dict.get(key, default)
def validate_key(
self, key: str, validator: Type[T], default: Optional[Any] = None
) -> T:
value = self.get(key=key, default=default)
"""
Parameters
----------
key
Name of they key in the dict to validate
validator
The validator to use for the key's value
default
If the key's value is None, use this as the default
Returns
-------
An instance of the specified validator
"""
value = self.dict.get(key, default)
if value is None:
raise self._validation_exception(
f"{key} is missing when it should be present."
@ -89,5 +144,5 @@ class DictValidator(Validator):
return validator(
name=f"{self.name}.{key}",
value=self.get(key=key, default=default),
value=value,
)

View file

@ -67,11 +67,11 @@ class SubscriptionValidator(StrictDictValidator):
return subscription_class(
name=self.name,
options=self.preset.get(self.preset.subscription_source_name),
ytdl_opts=self.preset.get("ytdl_options"),
post_process=self.preset.get("post_process"),
overrides=self.preset.get("overrides"),
output_path=self.preset.get("output_path"),
options=self.preset.dict.get(self.preset.subscription_source_name),
ytdl_opts=self.preset.dict.get("ytdl_options"),
post_process=self.preset.dict.get("post_process"),
overrides=self.preset.dict.get("overrides"),
output_path=self.preset.dict.get("output_path"),
)
@classmethod