map funcs
This commit is contained in:
parent
d35c8e9965
commit
689dfe8673
4 changed files with 84 additions and 19 deletions
|
|
@ -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 default is not None:
|
if key not in mapping.value:
|
||||||
return mapping.value.get(key, default=default)
|
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]
|
return mapping.value[key]
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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"""
|
||||||
|
|
|
||||||
48
tests/unit/script/functions/test_map_functions.py
Normal file
48
tests/unit/script/functions/test_map_functions.py
Normal 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()
|
||||||
Loading…
Reference in a new issue