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.resolvable import AnyArgument
from ytdl_sub.script.types.resolvable import Hashable
from ytdl_sub.script.utils.exceptions import KeyDoesNotExistRuntimeException
class MapFunctions:
@ -12,6 +13,11 @@ class MapFunctions:
Return ``key``'s value within the Map. If ``key`` does not exist, and ``default`` is
provided, it will return ``default``. Otherwise, will error.
"""
if default is not None:
return mapping.value.get(key, default=default)
if key not in mapping.value:
if default is not None:
return default
raise KeyDoesNotExistRuntimeException(
f"Tried to call %map_get with key {key.value}, but it does not exist"
)
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.exceptions import UNREACHABLE
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.type_checking import FunctionSpec
from ytdl_sub.script.utils.type_checking import is_union
@ -189,7 +190,7 @@ class BuiltInFunction(Function, BuiltInFunctionType):
try:
return self.callable(*resolved_arguments)
except UserThrownRuntimeError:
except (UserThrownRuntimeError, RuntimeException):
raise
except Exception as exc:
raise FunctionRuntimeException(

View file

@ -2,15 +2,14 @@ from abc import ABC
from ytdl_sub.utils.exceptions import ValidationException
###################################################################################################
# USER EXCEPTIONS
class UserException(ValidationException, ABC):
"""It's the user's fault!"""
class RuntimeException(ValueError, ABC):
"""Exception thrown at runtime during resolution"""
class InvalidSyntaxException(UserException):
"""Syntax is incorrect"""
@ -47,18 +46,6 @@ class CycleDetected(UserException):
"""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):
"""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 "
"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()