map funcs

This commit is contained in:
Jesse Bannon 2023-11-30 08:36:19 -08:00
parent d35c8e9965
commit 689dfe8673
4 changed files with 84 additions and 19 deletions

View file

@ -3,6 +3,7 @@ from typing import Optional
from ytdl_sub.script.types.map import Map from ytdl_sub.script.types.map import Map
from ytdl_sub.script.types.resolvable import AnyArgument from ytdl_sub.script.types.resolvable import AnyArgument
from ytdl_sub.script.types.resolvable import Hashable from ytdl_sub.script.types.resolvable import Hashable
from ytdl_sub.script.utils.exceptions import KeyDoesNotExistRuntimeException
class MapFunctions: class MapFunctions:
@ -12,6 +13,11 @@ class MapFunctions:
Return ``key``'s value within the Map. If ``key`` does not exist, and ``default`` is Return ``key``'s value within the Map. If ``key`` does not exist, and ``default`` is
provided, it will return ``default``. Otherwise, will error. provided, it will return ``default``. Otherwise, will error.
""" """
if key not in mapping.value:
if default is not None: if default is not None:
return mapping.value.get(key, default=default) return default
raise KeyDoesNotExistRuntimeException(
f"Tried to call %map_get with key {key.value}, but it does not exist"
)
return mapping.value[key] return mapping.value[key]

View file

@ -26,6 +26,7 @@ from ytdl_sub.script.types.variable_dependency import VariableDependency
from ytdl_sub.script.utils.exception_formatters import FunctionArgumentsExceptionFormatter from ytdl_sub.script.utils.exception_formatters import FunctionArgumentsExceptionFormatter
from ytdl_sub.script.utils.exceptions import UNREACHABLE from ytdl_sub.script.utils.exceptions import UNREACHABLE
from ytdl_sub.script.utils.exceptions import FunctionRuntimeException from ytdl_sub.script.utils.exceptions import FunctionRuntimeException
from ytdl_sub.script.utils.exceptions import RuntimeException
from ytdl_sub.script.utils.exceptions import UserThrownRuntimeError from ytdl_sub.script.utils.exceptions import UserThrownRuntimeError
from ytdl_sub.script.utils.type_checking import FunctionSpec from ytdl_sub.script.utils.type_checking import FunctionSpec
from ytdl_sub.script.utils.type_checking import is_union from ytdl_sub.script.utils.type_checking import is_union
@ -189,7 +190,7 @@ class BuiltInFunction(Function, BuiltInFunctionType):
try: try:
return self.callable(*resolved_arguments) return self.callable(*resolved_arguments)
except UserThrownRuntimeError: except (UserThrownRuntimeError, RuntimeException):
raise raise
except Exception as exc: except Exception as exc:
raise FunctionRuntimeException( raise FunctionRuntimeException(

View file

@ -2,15 +2,14 @@ from abc import ABC
from ytdl_sub.utils.exceptions import ValidationException from ytdl_sub.utils.exceptions import ValidationException
###################################################################################################
# USER EXCEPTIONS
class UserException(ValidationException, ABC): class UserException(ValidationException, ABC):
"""It's the user's fault!""" """It's the user's fault!"""
class RuntimeException(ValueError, ABC):
"""Exception thrown at runtime during resolution"""
class InvalidSyntaxException(UserException): class InvalidSyntaxException(UserException):
"""Syntax is incorrect""" """Syntax is incorrect"""
@ -47,18 +46,6 @@ class CycleDetected(UserException):
"""A cycle exists within a user's script""" """A cycle exists within a user's script"""
class FunctionRuntimeException(RuntimeException):
"""Exception thrown when a ytdl-sub function has an error occur at runtime"""
class KeyNotHashableRuntimeException(RuntimeException):
"""Map tried to use a non-hashable key at runtime"""
class FunctionDoesNotExistRuntimeException(RuntimeException):
"""Tried to get a function that does not exist"""
class UserThrownRuntimeError(ValidationException): class UserThrownRuntimeError(ValidationException):
"""An error explicitly thrown by the user via a function""" """An error explicitly thrown by the user via a function"""
@ -72,3 +59,26 @@ UNREACHABLE = _UnreachableSyntaxException(
"Please upload your config/subscription file(s) to and make a GitHub issue at " "Please upload your config/subscription file(s) to and make a GitHub issue at "
"https://github.com/jmbannon/ytdl-sub/issues" "https://github.com/jmbannon/ytdl-sub/issues"
) )
###################################################################################################
# RUNTIME EXCEPTIONS
class RuntimeException(ValueError, ABC):
"""Exception thrown at runtime during resolution"""
class FunctionRuntimeException(RuntimeException):
"""Exception thrown when a ytdl-sub function has an error occur at runtime"""
class KeyNotHashableRuntimeException(RuntimeException):
"""Map tried to use a non-hashable key at runtime"""
class FunctionDoesNotExistRuntimeException(RuntimeException):
"""Tried to get a function that does not exist"""
class KeyDoesNotExistRuntimeException(RuntimeException):
"""Tried to access a key on a map that does not exist, with no default"""

View file

@ -0,0 +1,48 @@
import re
import pytest
from ytdl_sub.script.script import Script
from ytdl_sub.script.utils.exceptions import KeyDoesNotExistRuntimeException
class TestMapFunctions:
def test_map_get(self):
output = (
Script(
{
"input_map": "{{'key': 'value'}}",
"output": "{%map_get(input_map, 'key')}",
}
)
.resolve(update=True)
.get("output")
.native
)
assert output == "value"
def test_map_get_optional(self):
output = (
Script(
{
"input_map": "{{'key': 'value'}}",
"output": "{%map_get(input_map, 'dne', 'optional_value')}",
}
)
.resolve(update=True)
.get("output")
.native
)
assert output == "optional_value"
def test_map_get_errors_missing_key(self):
with pytest.raises(
KeyDoesNotExistRuntimeException,
match=re.escape("Tried to call %map_get with key dne, but it does not exist"),
):
Script(
{
"input_map": "{{'key': 'value'}}",
"output": "{%map_get(input_map, 'dne')}",
}
).resolve()