json friendly array output
This commit is contained in:
parent
d50c0c6559
commit
1e68a99cdd
9 changed files with 41 additions and 33 deletions
|
|
@ -51,6 +51,7 @@ STRINGS_ONLY_ARGS = InvalidSyntaxException(
|
||||||
"Strings can only be used as arguments to functions, maps, or arrays"
|
"Strings can only be used as arguments to functions, maps, or arrays"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def UNEXPECTED_CHAR_ARGUMENT(parser: ArgumentParser):
|
def UNEXPECTED_CHAR_ARGUMENT(parser: ArgumentParser):
|
||||||
return InvalidSyntaxException(f"Unexpected character when parsing {parser.value} arguments")
|
return InvalidSyntaxException(f"Unexpected character when parsing {parser.value} arguments")
|
||||||
|
|
||||||
|
|
@ -76,9 +77,11 @@ def _is_variable_start(char: str) -> bool:
|
||||||
def _is_numeric_start(char: str) -> bool:
|
def _is_numeric_start(char: str) -> bool:
|
||||||
return char.isnumeric() or char == "-"
|
return char.isnumeric() or char == "-"
|
||||||
|
|
||||||
|
|
||||||
def _is_string_start(char: str) -> bool:
|
def _is_string_start(char: str) -> bool:
|
||||||
return char in ["'", '"']
|
return char in ["'", '"']
|
||||||
|
|
||||||
|
|
||||||
def _is_breakable(char: str) -> bool:
|
def _is_breakable(char: str) -> bool:
|
||||||
return char in ["}", ",", ")", "]"] or char.isspace()
|
return char in ["}", ",", ")", "]"] or char.isspace()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import json
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
@ -6,6 +7,7 @@ from typing import Set
|
||||||
from ytdl_sub.script.types.resolvable import ArgumentType
|
from ytdl_sub.script.types.resolvable import ArgumentType
|
||||||
from ytdl_sub.script.types.resolvable import NonHashable
|
from ytdl_sub.script.types.resolvable import NonHashable
|
||||||
from ytdl_sub.script.types.resolvable import Resolvable
|
from ytdl_sub.script.types.resolvable import Resolvable
|
||||||
|
from ytdl_sub.script.types.resolvable import ResolvableToJson
|
||||||
from ytdl_sub.script.types.variable import FunctionArgument
|
from ytdl_sub.script.types.variable import FunctionArgument
|
||||||
from ytdl_sub.script.types.variable import Variable
|
from ytdl_sub.script.types.variable import Variable
|
||||||
from ytdl_sub.script.types.variable_dependency import VariableDependency
|
from ytdl_sub.script.types.variable_dependency import VariableDependency
|
||||||
|
|
@ -15,9 +17,6 @@ from ytdl_sub.script.types.variable_dependency import VariableDependency
|
||||||
class Array(NonHashable):
|
class Array(NonHashable):
|
||||||
value: List[Resolvable]
|
value: List[Resolvable]
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f"[{', '.join([str(val.value) for val in self.value])}]"
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class UnresolvedArray(Array, VariableDependency, ArgumentType):
|
class UnresolvedArray(Array, VariableDependency, ArgumentType):
|
||||||
|
|
@ -63,5 +62,5 @@ class UnresolvedArray(Array, VariableDependency, ArgumentType):
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class ResolvedArray(Array, Resolvable):
|
class ResolvedArray(Array, ResolvableToJson):
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ from ytdl_sub.script.types.resolvable import ArgumentType
|
||||||
from ytdl_sub.script.types.resolvable import Hashable
|
from ytdl_sub.script.types.resolvable import Hashable
|
||||||
from ytdl_sub.script.types.resolvable import NonHashable
|
from ytdl_sub.script.types.resolvable import NonHashable
|
||||||
from ytdl_sub.script.types.resolvable import Resolvable
|
from ytdl_sub.script.types.resolvable import Resolvable
|
||||||
|
from ytdl_sub.script.types.resolvable import ResolvableToJson
|
||||||
from ytdl_sub.script.types.variable import FunctionArgument
|
from ytdl_sub.script.types.variable import FunctionArgument
|
||||||
from ytdl_sub.script.types.variable import Variable
|
from ytdl_sub.script.types.variable import Variable
|
||||||
from ytdl_sub.script.types.variable_dependency import VariableDependency
|
from ytdl_sub.script.types.variable_dependency import VariableDependency
|
||||||
|
|
@ -18,22 +19,6 @@ from ytdl_sub.utils.exceptions import StringFormattingException
|
||||||
class Map(NonHashable):
|
class Map(NonHashable):
|
||||||
value: Dict[Hashable, Resolvable]
|
value: Dict[Hashable, Resolvable]
|
||||||
|
|
||||||
def to_native(self) -> Dict:
|
|
||||||
output = {}
|
|
||||||
for key, value in self.value.items():
|
|
||||||
native_key = key.value
|
|
||||||
if isinstance(value, Map):
|
|
||||||
native_value = value.to_native()
|
|
||||||
else:
|
|
||||||
native_value = value.value
|
|
||||||
|
|
||||||
output[native_key] = native_value
|
|
||||||
|
|
||||||
return output
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return json.dumps(self.to_native())
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class UnresolvedMap(Map, VariableDependency, ArgumentType):
|
class UnresolvedMap(Map, VariableDependency, ArgumentType):
|
||||||
|
|
@ -92,5 +77,5 @@ class UnresolvedMap(Map, VariableDependency, ArgumentType):
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class ResolvedMap(Map, Resolvable):
|
class ResolvedMap(Map, ResolvableToJson):
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
|
import json
|
||||||
from abc import ABC
|
from abc import ABC
|
||||||
|
from abc import abstractmethod
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Generic
|
from typing import Generic
|
||||||
|
|
@ -40,6 +42,22 @@ class NonHashable(ABC):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ResolvableToJson(Resolvable, ABC):
|
||||||
|
@classmethod
|
||||||
|
def _to_native(cls, to_convert: Resolvable) -> Any:
|
||||||
|
if isinstance(to_convert.value, list):
|
||||||
|
return [cls._to_native(val) for val in to_convert.value]
|
||||||
|
if isinstance(to_convert.value, dict):
|
||||||
|
return {
|
||||||
|
cls._to_native(key): cls._to_native(value)
|
||||||
|
for key, value in to_convert.value.items()
|
||||||
|
}
|
||||||
|
return to_convert.value
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return json.dumps(self._to_native(self))
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class ResolvableT(Hashable, ABC, Generic[T]):
|
class ResolvableT(Hashable, ABC, Generic[T]):
|
||||||
value: T
|
value: T
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ class TestSyntaxTree:
|
||||||
"bb": "b",
|
"bb": "b",
|
||||||
"cc": "{%custom_func(aa, bb)}",
|
"cc": "{%custom_func(aa, bb)}",
|
||||||
}
|
}
|
||||||
).resolve() == {"aa": String("a"), "bb": String("b"), "cc": String("return [a, b]")}
|
).resolve() == {"aa": String("a"), "bb": String("b"), "cc": String('return ["a", "b"]')}
|
||||||
|
|
||||||
def test_simple(self):
|
def test_simple(self):
|
||||||
assert Script({"a": "a", "b": "{b_}", "b_": "b"}).resolve() == {
|
assert Script({"a": "a", "b": "{b_}", "b_": "b"}).resolve() == {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ class TestArray:
|
||||||
|
|
||||||
def test_return_as_str(self):
|
def test_return_as_str(self):
|
||||||
assert Script({"array": "str: {['a', 3.14]}"}).resolve() == {
|
assert Script({"array": "str: {['a', 3.14]}"}).resolve() == {
|
||||||
"array": String("str: [a, 3.14]")
|
"array": String('str: ["a", 3.14]')
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_nested_array(self):
|
def test_nested_array(self):
|
||||||
|
|
@ -111,4 +111,4 @@ class TestArray:
|
||||||
"bb": "b",
|
"bb": "b",
|
||||||
"cc": "{%custom_func(aa, bb)}",
|
"cc": "{%custom_func(aa, bb)}",
|
||||||
}
|
}
|
||||||
).resolve() == {"aa": String("a"), "bb": String("b"), "cc": String("return [a, b]")}
|
).resolve() == {"aa": String("a"), "bb": String("b"), "cc": String('return ["a", "b"]')}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,9 @@ from typing import Tuple
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ytdl_sub.script.parser import NUMERICS_INVALID_CHAR, STRINGS_ONLY_ARGS
|
from ytdl_sub.script.parser import NUMERICS_INVALID_CHAR
|
||||||
from ytdl_sub.script.parser import NUMERICS_ONLY_ARGS
|
from ytdl_sub.script.parser import NUMERICS_ONLY_ARGS
|
||||||
|
from ytdl_sub.script.parser import STRINGS_ONLY_ARGS
|
||||||
from ytdl_sub.script.parser import UNEXPECTED_CHAR_ARGUMENT
|
from ytdl_sub.script.parser import UNEXPECTED_CHAR_ARGUMENT
|
||||||
from ytdl_sub.script.parser import UNEXPECTED_COMMA_ARGUMENT
|
from ytdl_sub.script.parser import UNEXPECTED_COMMA_ARGUMENT
|
||||||
from ytdl_sub.script.parser import ArgumentParser
|
from ytdl_sub.script.parser import ArgumentParser
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,9 @@ from typing import Tuple
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ytdl_sub.script.parser import NUMERICS_INVALID_CHAR, STRINGS_ONLY_ARGS
|
from ytdl_sub.script.parser import NUMERICS_INVALID_CHAR
|
||||||
from ytdl_sub.script.parser import NUMERICS_ONLY_ARGS
|
from ytdl_sub.script.parser import NUMERICS_ONLY_ARGS
|
||||||
|
from ytdl_sub.script.parser import STRINGS_ONLY_ARGS
|
||||||
from ytdl_sub.script.parser import UNEXPECTED_CHAR_ARGUMENT
|
from ytdl_sub.script.parser import UNEXPECTED_CHAR_ARGUMENT
|
||||||
from ytdl_sub.script.parser import UNEXPECTED_COMMA_ARGUMENT
|
from ytdl_sub.script.parser import UNEXPECTED_COMMA_ARGUMENT
|
||||||
from ytdl_sub.script.parser import ArgumentParser
|
from ytdl_sub.script.parser import ArgumentParser
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,9 @@ from typing import Tuple
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ytdl_sub.script.parser import NUMERICS_INVALID_CHAR, STRINGS_ONLY_ARGS
|
from ytdl_sub.script.parser import NUMERICS_INVALID_CHAR
|
||||||
from ytdl_sub.script.parser import NUMERICS_ONLY_ARGS
|
from ytdl_sub.script.parser import NUMERICS_ONLY_ARGS
|
||||||
|
from ytdl_sub.script.parser import STRINGS_ONLY_ARGS
|
||||||
from ytdl_sub.script.parser import UNEXPECTED_CHAR_ARGUMENT
|
from ytdl_sub.script.parser import UNEXPECTED_CHAR_ARGUMENT
|
||||||
from ytdl_sub.script.parser import UNEXPECTED_COMMA_ARGUMENT
|
from ytdl_sub.script.parser import UNEXPECTED_COMMA_ARGUMENT
|
||||||
from ytdl_sub.script.parser import ArgumentParser
|
from ytdl_sub.script.parser import ArgumentParser
|
||||||
|
|
@ -21,10 +22,10 @@ class TestString:
|
||||||
"string",
|
"string",
|
||||||
[
|
[
|
||||||
"{'323'}",
|
"{'323'}",
|
||||||
"{ \"4253\" }",
|
'{ "4253" }',
|
||||||
"{\"hi\"}",
|
'{"hi"}',
|
||||||
"{ \"asfsd\" }",
|
'{ "asfsd" }',
|
||||||
"{\"sdfasf\"}",
|
'{"sdfasf"}',
|
||||||
"{ '3fsdf' }",
|
"{ '3fsdf' }",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue