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",
nargs="*",
help="path to subscription files, uses subscriptions.yaml if not provided",
default="subscriptions.yaml",
default=["subscriptions.yaml"],
)
###################################################################################################
# DOWNLOAD PARSER

View file

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

View file

@ -6,7 +6,6 @@ from typing import Optional
from typing import Tuple
from typing import Type
import yaml
from mergedeep import mergedeep
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 PluginOptions
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.string_formatter_validators import OverridesStringFormatterValidator
from ytdl_sub.validators.validators import DictValidator
@ -280,9 +280,7 @@ class Preset(StrictDictValidator):
-------
List of presets, for each one in the subscription yaml
"""
# TODO: Create separate yaml file loader class
with open(subscription_path, "r", encoding="utf-8") as file:
subscription_dict = yaml.safe_load(file)
subscription_dict = load_yaml(file_path=subscription_path)
subscriptions: List["Preset"] = []
for subscription_key, subscription_object in subscription_dict.items():

View file

@ -12,3 +12,11 @@ class StringFormattingVariableNotFoundException(StringFormattingException):
class DownloadArchiveException(ValueError):
"""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)