From 94e028536feed84f36f012b1b47ffb28f183188a Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Sun, 10 Dec 2023 19:43:07 -0800 Subject: [PATCH] JSON functions WIP, need to add new way to specify strings that are json friendly --- src/ytdl_sub/entries/entry.py | 5 ++- src/ytdl_sub/script/functions/__init__.py | 2 ++ .../script/functions/json_functions.py | 36 +++++++++++++++++++ .../script/functions/test_string_functions.py | 3 -- 4 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 src/ytdl_sub/script/functions/json_functions.py diff --git a/src/ytdl_sub/entries/entry.py b/src/ytdl_sub/entries/entry.py index c133f862..8ec92051 100644 --- a/src/ytdl_sub/entries/entry.py +++ b/src/ytdl_sub/entries/entry.py @@ -33,7 +33,10 @@ class Entry(BaseEntry, Scriptable): def _add_entry_kwargs_to_script(self) -> None: # Add entry metadata, but avoid the `.add()` helper since it also adds sanitized self.unresolvable.remove(VARIABLES.entry_metadata.variable_name) - self.script.add({VARIABLES.entry_metadata.variable_name: f"{{{json.dumps(self._kwargs)}}}"}) + single_quote = "'" + replace_single_quote = "\\'" + entry_metadata_variable = f"{{%from_json('{json.dumps(self._kwargs, ensure_ascii=False).replace(single_quote, replace_single_quote)}')}}" + self.script.add({VARIABLES.entry_metadata.variable_name: entry_metadata_variable}) self.update_script() def initialize_script(self, other: Optional[Scriptable] = None) -> "Entry": diff --git a/src/ytdl_sub/script/functions/__init__.py b/src/ytdl_sub/script/functions/__init__.py index 5e272cb2..fe196cf1 100644 --- a/src/ytdl_sub/script/functions/__init__.py +++ b/src/ytdl_sub/script/functions/__init__.py @@ -6,6 +6,7 @@ from ytdl_sub.script.functions.boolean_functions import BooleanFunctions from ytdl_sub.script.functions.conditional_functions import ConditionalFunctions from ytdl_sub.script.functions.date_functions import DateFunctions from ytdl_sub.script.functions.error_functions import ErrorFunctions +from ytdl_sub.script.functions.json_functions import JsonFunctions from ytdl_sub.script.functions.map_functions import MapFunctions from ytdl_sub.script.functions.numeric_functions import NumericFunctions from ytdl_sub.script.functions.regex_functions import RegexFunctions @@ -24,6 +25,7 @@ class Functions( ErrorFunctions, RegexFunctions, DateFunctions, + JsonFunctions, ): _custom_functions: Dict[str, Callable[..., Resolvable]] = {} diff --git a/src/ytdl_sub/script/functions/json_functions.py b/src/ytdl_sub/script/functions/json_functions.py new file mode 100644 index 00000000..d13a33f0 --- /dev/null +++ b/src/ytdl_sub/script/functions/json_functions.py @@ -0,0 +1,36 @@ +import json +from typing import Any + +from ytdl_sub.script.types.array import Array +from ytdl_sub.script.types.map import Map +from ytdl_sub.script.types.resolvable import AnyArgument +from ytdl_sub.script.types.resolvable import Boolean +from ytdl_sub.script.types.resolvable import Float +from ytdl_sub.script.types.resolvable import Integer +from ytdl_sub.script.types.resolvable import Resolvable +from ytdl_sub.script.types.resolvable import String +from ytdl_sub.script.utils.exceptions import UNREACHABLE + + +def _from_json(out: Any) -> Resolvable: + if out is None: + return String("") + if isinstance(out, int): + return Integer(out) + if isinstance(out, float): + return Float(out) + if isinstance(out, str): + return String(out) + if isinstance(out, bool): + return Boolean(out) + if isinstance(out, list): + return Array(value=[_from_json(arg) for arg in out]) + if isinstance(out, dict): + return Map(value={_from_json(key): _from_json(value) for key, value in out.items()}) + raise UNREACHABLE + + +class JsonFunctions: + @staticmethod + def from_json(argument: AnyArgument) -> AnyArgument: + return _from_json(json.loads(argument.value)) diff --git a/tests/unit/script/functions/test_string_functions.py b/tests/unit/script/functions/test_string_functions.py index ad34a75a..ded9b66e 100644 --- a/tests/unit/script/functions/test_string_functions.py +++ b/tests/unit/script/functions/test_string_functions.py @@ -1,9 +1,6 @@ import pytest from unit.script.conftest import single_variable_output -from ytdl_sub.script.script import Script - - class TestNumericFunctions: @pytest.mark.parametrize( "values, expected_output",