From 7483a1315b7194f237a85baf7c497ce4958bf572 Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Tue, 7 Nov 2023 09:25:10 -0800 Subject: [PATCH] add map type --- src/ytdl_sub/script/functions/__init__.py | 3 ++- .../script/functions/map_functions.py | 21 +++++++++++++++++++ src/ytdl_sub/script/types/resolvable.py | 9 +++++++- tests/unit/script/test_parser.py | 8 +++++++ 4 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 src/ytdl_sub/script/functions/map_functions.py diff --git a/src/ytdl_sub/script/functions/__init__.py b/src/ytdl_sub/script/functions/__init__.py index 5247143e..46d494f4 100644 --- a/src/ytdl_sub/script/functions/__init__.py +++ b/src/ytdl_sub/script/functions/__init__.py @@ -1,10 +1,11 @@ from typing import Optional from ytdl_sub.script.functions.array_functions import ArrayFunctions +from ytdl_sub.script.functions.map_functions import MapFunctions from ytdl_sub.script.functions.numeric_functions import NumericFunctions from ytdl_sub.script.functions.special_functions import SpecialFunctions from ytdl_sub.script.functions.string_functions import StringFunctions -class Functions(StringFunctions, NumericFunctions, SpecialFunctions, ArrayFunctions): +class Functions(StringFunctions, NumericFunctions, SpecialFunctions, ArrayFunctions, MapFunctions): pass diff --git a/src/ytdl_sub/script/functions/map_functions.py b/src/ytdl_sub/script/functions/map_functions.py new file mode 100644 index 00000000..d5ef7010 --- /dev/null +++ b/src/ytdl_sub/script/functions/map_functions.py @@ -0,0 +1,21 @@ +from typing import List, Dict + +from ytdl_sub.script.types.resolvable import Array, Map +from ytdl_sub.script.types.resolvable import Resolvable +from ytdl_sub.utils.exceptions import StringFormattingException + + +class MapFunctions: + @staticmethod + def map(*key_values: Array) -> Map: + output: Dict[Resolvable, Resolvable] = {} + + for key_value in key_values: + if len(key_value.value) != 2: + raise StringFormattingException( + "%map must take Arrays containing pairs of keys and values" + ) + + output[key_value.value[0]] = key_value.value[1] + + return Map(output) diff --git a/src/ytdl_sub/script/types/resolvable.py b/src/ytdl_sub/script/types/resolvable.py index 9ccc63b3..62630215 100644 --- a/src/ytdl_sub/script/types/resolvable.py +++ b/src/ytdl_sub/script/types/resolvable.py @@ -1,7 +1,7 @@ from abc import ABC from abc import abstractmethod from dataclasses import dataclass -from typing import Any +from typing import Any, Dict from typing import Generic from typing import List from typing import TypeVar @@ -66,3 +66,10 @@ class Array(Resolvable): def __str__(self) -> str: return f"[{', '.join([val.value for val in self.value])}]" + +@dataclass(frozen=True) +class Map(Resolvable): + value: Dict[Resolvable, Resolvable] + + def __str__(self) -> str: + return f"[{', '.join([val.value for val in self.value])}]" \ No newline at end of file diff --git a/tests/unit/script/test_parser.py b/tests/unit/script/test_parser.py index 9788243a..7a50113a 100644 --- a/tests/unit/script/test_parser.py +++ b/tests/unit/script/test_parser.py @@ -35,6 +35,14 @@ class TestParser: parsed_extend = parse("hi {%extend(['elem1', 'elem2'], ['elem3'], [], ['elem4'])}") assert False + def test_map(self): + parsed = parse("hello {%map(['elem1', 'elem2'])}") + parsed_empty = parse("hello {%map()}") + parsed_with_var = parse("hello {%map([variable_name, 'elem2'])}") + parsed_extend = parse("hi {%map([variable_name, 'elem2'], ['elem3', variable_name])}") + parsed_extend.resolve({}) + assert False + def test_conditional(self): parsed = parse("hello {%if(True, 'hi', 3.4)}") assert parsed == SyntaxTree(