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 Any
from typing import List
from typing import Optional from typing import Optional
from typing import Type from typing import Type
from typing import TypeVar from typing import TypeVar
@ -7,18 +8,20 @@ from ytdl_subscribe.validators.exceptions import ValidationException
class Validator: 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 # The python type that value should be
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 __validate_value(self): def __init__(self, name: str, value: Any):
""" self.name = name
Returns self._value = value
-------
Validation exception to raise when the value's type is not the expected type
"""
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
@ -27,36 +30,63 @@ class Validator:
error_message=f"should be of type {expected_value_type_name}." 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 @property
def value(self) -> object: def value(self) -> object:
"""
Returns
-------
Value of the validator
"""
return self._value 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}: " prefix = f"Validation error in {self.name}: "
return ValidationException(f"{prefix}{error_message}") return ValidationException(f"{prefix}{error_message}")
class BoolValidator(Validator): class BoolValidator(Validator):
"""
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:
"""
Returns
-------
Boolean value
"""
return self._value return self._value
class StringValidator(Validator): class StringValidator(Validator):
"""
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:
"""
Returns
-------
String value
"""
return self._value return self._value
@ -64,24 +94,49 @@ T = TypeVar("T", bound=Validator)
class DictValidator(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 = dict
expected_value_type_name = "object" # for non-python users expected_value_type_name = "object"
@property @property
def dict(self) -> dict: def dict(self) -> dict:
"""
Returns
-------
Dictionary value
"""
return self._value return self._value
@property @property
def keys(self): def keys(self) -> List[str]:
"""
Returns
-------
Sorted list of dictionary keys
"""
return sorted(list(self.dict.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( def validate_key(
self, key: str, validator: Type[T], default: Optional[Any] = None self, key: str, validator: Type[T], default: Optional[Any] = None
) -> T: ) -> 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: if value is None:
raise self._validation_exception( raise self._validation_exception(
f"{key} is missing when it should be present." f"{key} is missing when it should be present."
@ -89,5 +144,5 @@ class DictValidator(Validator):
return validator( return validator(
name=f"{self.name}.{key}", 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( return subscription_class(
name=self.name, name=self.name,
options=self.preset.get(self.preset.subscription_source_name), options=self.preset.dict.get(self.preset.subscription_source_name),
ytdl_opts=self.preset.get("ytdl_options"), ytdl_opts=self.preset.dict.get("ytdl_options"),
post_process=self.preset.get("post_process"), post_process=self.preset.dict.get("post_process"),
overrides=self.preset.get("overrides"), overrides=self.preset.dict.get("overrides"),
output_path=self.preset.get("output_path"), output_path=self.preset.dict.get("output_path"),
) )
@classmethod @classmethod