Yaml error handling (#45)

This commit is contained in:
Jesse Bannon 2022-05-27 22:14:50 -07:00 committed by GitHub
parent f3c06ec15c
commit ec1cc534ea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 92 additions and 10 deletions

View file

@ -22,7 +22,7 @@ subscription_parser.add_argument(
metavar="SUBPATH", metavar="SUBPATH",
nargs="*", nargs="*",
help="path to subscription files, uses subscriptions.yaml if not provided", help="path to subscription files, uses subscriptions.yaml if not provided",
default="subscriptions.yaml", default=["subscriptions.yaml"],
) )
################################################################################################### ###################################################################################################
# DOWNLOAD PARSER # DOWNLOAD PARSER

View file

@ -1,7 +1,6 @@
from typing import Any from typing import Any
import yaml from ytdl_sub.utils.yaml import load_yaml
from ytdl_sub.validators.strict_dict_validator import StrictDictValidator from ytdl_sub.validators.strict_dict_validator import StrictDictValidator
from ytdl_sub.validators.validators import LiteralDictValidator from ytdl_sub.validators.validators import LiteralDictValidator
from ytdl_sub.validators.validators import StringValidator from ytdl_sub.validators.validators import StringValidator
@ -56,7 +55,5 @@ class ConfigFile(StrictDictValidator):
------- -------
Config file validator Config file validator
""" """
# TODO: Create separate yaml file loader class config_dict = load_yaml(file_path=config_path)
with open(config_path, "r", encoding="utf-8") as file:
config_dict = yaml.safe_load(file)
return ConfigFile.from_dict(config_dict) return ConfigFile.from_dict(config_dict)

View file

@ -6,7 +6,6 @@ from typing import Optional
from typing import Tuple from typing import Tuple
from typing import Type from typing import Type
import yaml
from mergedeep import mergedeep from mergedeep import mergedeep
from ytdl_sub.config.config_file import ConfigFile from ytdl_sub.config.config_file import ConfigFile
@ -20,6 +19,7 @@ from ytdl_sub.downloaders.downloader import DownloaderValidator
from ytdl_sub.plugins.plugin import Plugin from ytdl_sub.plugins.plugin import Plugin
from ytdl_sub.plugins.plugin import PluginOptions from ytdl_sub.plugins.plugin import PluginOptions
from ytdl_sub.utils.exceptions import StringFormattingVariableNotFoundException from ytdl_sub.utils.exceptions import StringFormattingVariableNotFoundException
from ytdl_sub.utils.yaml import load_yaml
from ytdl_sub.validators.strict_dict_validator import StrictDictValidator from ytdl_sub.validators.strict_dict_validator import StrictDictValidator
from ytdl_sub.validators.string_formatter_validators import OverridesStringFormatterValidator from ytdl_sub.validators.string_formatter_validators import OverridesStringFormatterValidator
from ytdl_sub.validators.validators import DictValidator from ytdl_sub.validators.validators import DictValidator
@ -280,9 +280,7 @@ class Preset(StrictDictValidator):
------- -------
List of presets, for each one in the subscription yaml List of presets, for each one in the subscription yaml
""" """
# TODO: Create separate yaml file loader class subscription_dict = load_yaml(file_path=subscription_path)
with open(subscription_path, "r", encoding="utf-8") as file:
subscription_dict = yaml.safe_load(file)
subscriptions: List["Preset"] = [] subscriptions: List["Preset"] = []
for subscription_key, subscription_object in subscription_dict.items(): for subscription_key, subscription_object in subscription_dict.items():

View file

@ -12,3 +12,11 @@ class StringFormattingVariableNotFoundException(StringFormattingException):
class DownloadArchiveException(ValueError): class DownloadArchiveException(ValueError):
"""Any user or file errors caused by download archive or mapping files""" """Any user or file errors caused by download archive or mapping files"""
class FileNotFoundException(ValidationException):
"""Any user file that's expected to exist, but is not found"""
class InvalidYamlException(ValidationException):
"""User yaml that is invalid"""

View file

@ -0,0 +1,38 @@
import os.path
from typing import Dict
import yaml
from yaml import YAMLError
from ytdl_sub.utils.exceptions import FileNotFoundException
from ytdl_sub.utils.exceptions import InvalidYamlException
def load_yaml(file_path: str) -> Dict:
"""
Parameters
----------
file_path
Path of the file
Returns
-------
Dict representation of the yaml file
Raises
------
FileNotFoundException
The file does not exist
InvalidYamlException
The file has invalid yaml
"""
if not os.path.isfile(file_path):
raise FileNotFoundException(f"The file '{file_path}' does not exist.")
try:
with open(file_path, "r", encoding="utf-8") as file:
return yaml.safe_load(file)
except YAMLError as yaml_exception:
raise InvalidYamlException(
f"'{file_path}' has invalid YAML, copy-paste it into a YAML checker to find the issue."
) from yaml_exception

View file

View file

@ -0,0 +1,41 @@
import tempfile
import pytest
from ytdl_sub.utils.exceptions import FileNotFoundException
from ytdl_sub.utils.exceptions import InvalidYamlException
from ytdl_sub.utils.yaml import load_yaml
@pytest.fixture
def bad_yaml():
return """
this:
is:
bad:
asdf:
bad :
:yaml
"""
@pytest.fixture
def bad_yaml_file_path(bad_yaml):
with tempfile.NamedTemporaryFile(suffix=".yaml") as tmp_file:
tmp_file.write(bad_yaml.encode("utf-8"))
tmp_file.flush()
yield tmp_file.name
def test_load_yaml_file_not_found():
file_path = "does_not_exist.yaml"
with pytest.raises(FileNotFoundException, match=f"The file '{file_path}' does not exist."):
load_yaml(file_path=file_path)
def test_load_yaml_invalid_syntax(bad_yaml_file_path):
with pytest.raises(
InvalidYamlException,
match=f"'{bad_yaml_file_path}' has invalid YAML, copy-paste it into a YAML checker to find the issue.",
):
load_yaml(file_path=bad_yaml_file_path)