-
Notifications
You must be signed in to change notification settings - Fork 216
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
437 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
"""Built in actions for Jaseci""" | ||
from jaseci.jsorc.live_actions import jaseci_action | ||
from json import loads, dumps | ||
from re import compile | ||
|
||
internal = compile(r"\(([a-zA-Z0-9_\.\$]*?)\)") | ||
full = compile(r"^\{\{([a-zA-Z0-9_\.\$\(\)]*?)\}\}$") | ||
partial = compile(r"\{\{([a-zA-Z0-9_\.\$\(\)]*?)\}\}") | ||
|
||
|
||
def convert_dict(value) -> dict: | ||
try: | ||
return loads(value) | ||
except: | ||
return "Error JSON loads!" | ||
|
||
|
||
def convert_str(value) -> str: | ||
if isinstance(value, (dict, list)): | ||
return dumps(value) | ||
else: | ||
return "" if value == None else str(value) | ||
|
||
|
||
def get_deep_value(keys: list[str], source, default): | ||
if len(keys) == 0: | ||
return source | ||
|
||
key = keys.pop(0) | ||
_type = type(source) | ||
if _type is dict and key in source: | ||
return get_deep_value(keys, source[key], default) | ||
elif _type is list and key.isnumeric(): | ||
return get_deep_value(keys, source[int(key)], default) | ||
else: | ||
return default | ||
|
||
|
||
def get_value(jpath: str, source, default=None): | ||
while internal.search(jpath): | ||
for intern in internal.findall(jpath): | ||
jpath = jpath.replace( | ||
"(" + intern + ")", convert_str(get_value(intern, source, "")) | ||
) | ||
|
||
if jpath: | ||
keys = jpath.split(".") | ||
key = keys.pop(0) | ||
if key == "$": | ||
if isinstance(source, (dict, list)): | ||
return get_deep_value(keys, source, default) | ||
elif len(keys) == 0: | ||
return source | ||
elif key == "$s": | ||
if isinstance(source, (dict, list)): | ||
return convert_str(get_deep_value(keys, source, default)) | ||
elif len(keys) == 0: | ||
return convert_str(source) | ||
elif key == "$i": | ||
if isinstance(source, (dict, list)): | ||
value = get_deep_value(keys, source, default) | ||
return 0 if value == None else int(value) | ||
elif len(keys) == 0: | ||
return 0 if source == None else int(source) | ||
elif key == "$d": | ||
if isinstance(source, (dict, list)): | ||
return convert_dict(get_deep_value(keys, source, default)) | ||
elif len(keys) == 0: | ||
return convert_dict(source) | ||
else: | ||
pass | ||
# for future syntax | ||
return default | ||
|
||
|
||
def parse_str(key: str, value: str, target, source): | ||
matcher = full.match(value) | ||
if matcher: | ||
value = get_value(matcher.group(1), source) | ||
else: | ||
for jpath in partial.findall(value): | ||
value = value.replace( | ||
"{{" + jpath + "}}", convert_str(get_value(jpath, source, "")) | ||
) | ||
|
||
if key: | ||
target[key] = value | ||
else: | ||
return value | ||
|
||
|
||
def traverse_dict(target: dict, source): | ||
for key in target.keys(): | ||
traverse(key, target[key], target, source) | ||
|
||
|
||
def traverse_list(target: list, source): | ||
for key, value in enumerate(target): | ||
traverse(key, value, target, source) | ||
|
||
|
||
def traverse(key, value, target, source): | ||
_type = type(value) | ||
if _type is dict: | ||
traverse_dict(value, source) | ||
elif _type is list: | ||
traverse_list(value, source) | ||
elif _type is str: | ||
parse_str(key, value, target, source) | ||
|
||
|
||
@jaseci_action() | ||
def parse(source, target): | ||
""" | ||
Dynamic parsing of target dict or list | ||
Return - parsed target object | ||
""" | ||
_type = type(target) | ||
if _type is dict: | ||
traverse_dict(target, source) | ||
elif _type is list: | ||
traverse_list(target, source) | ||
elif _type is str: | ||
return parse_str(None, target, None, source) | ||
|
||
return target |
224 changes: 224 additions & 0 deletions
224
jaseci_core/jaseci/extens/act_lib/tests/fixtures/djson.jac
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
walker parser { | ||
can djson.parse; | ||
with entry { | ||
|
||
report "[1]: whole source"; | ||
report djson.parse( | ||
{"a": 1}, | ||
{"b": "{{$}}"} | ||
); | ||
|
||
report "[2]: whole source cast to string"; | ||
report djson.parse( | ||
{"a": 1}, | ||
{"b": "{{$s}}"} | ||
); | ||
|
||
report "[3]: int"; | ||
report djson.parse( | ||
{"a": 1}, | ||
{"b": "{{$.a}}"} | ||
); | ||
|
||
report "[4]: int cast to string"; | ||
report djson.parse( | ||
{"a": 1}, | ||
{"b": "{{$s.a}}"} | ||
); | ||
|
||
report "[5]: int partial"; | ||
report djson.parse({"a": 1}, | ||
{"b": "partial-{{$.a}}"} | ||
); | ||
|
||
report "[6]: string"; | ||
report djson.parse( | ||
{"a": "1"}, | ||
{"b": "{{$.a}}"} | ||
); | ||
|
||
report "[7]: string partial"; | ||
report djson.parse( | ||
{"a": "1"}, | ||
{"b": "partial-{{$.a}}"} | ||
); | ||
|
||
report "[8]: int list"; | ||
report djson.parse( | ||
{"a": [1]}, | ||
{"b": "{{$.a}}"} | ||
); | ||
|
||
report "[9]: int list cast to string"; | ||
report djson.parse( | ||
{"a": [1]}, | ||
{"b": "{{$s.a}}"} | ||
); | ||
|
||
report "[10]: int list partial"; | ||
report djson.parse( | ||
{"a": [1]}, | ||
{"b": "partial-{{$.a}}"} | ||
); | ||
|
||
report "[11]: int list index"; | ||
report djson.parse( | ||
{"a": [1]}, | ||
{"b": "{{$.a.0}}"} | ||
); | ||
|
||
report "[12]: string list"; | ||
report djson.parse( | ||
{"a": ["1"]}, | ||
{"b": "{{$.a}}"} | ||
); | ||
|
||
report "[13]: string list cast to string"; | ||
report djson.parse( | ||
{"a": ["1"]}, | ||
{"b": "{{$s.a}}"} | ||
); | ||
|
||
report "[14]: string list partial"; | ||
report djson.parse( | ||
{"a": ["1"]}, | ||
{"b": "partial-{{$.a}}"} | ||
); | ||
|
||
report "[15]: string list index"; | ||
report djson.parse( | ||
{"a": ["1"]}, | ||
{"b": "{{$.a.0}}"} | ||
); | ||
|
||
report "[16]: dict"; | ||
report djson.parse( | ||
{"a": {"test": 1}}, | ||
{"b": "{{$.a}}"} | ||
); | ||
|
||
report "[17]: dict cast to string"; | ||
report djson.parse( | ||
{"a": {"test": 1}}, | ||
{"b": "{{$s.a}}"} | ||
); | ||
|
||
report "[18]: dict partial"; | ||
report djson.parse( | ||
{"a": {"test": 1}}, | ||
{"b": "partial-{{$.a}}"} | ||
); | ||
|
||
report "[19]: nested dict"; | ||
report djson.parse( | ||
{"a": {"test": 1}}, | ||
{"b": "{{$.a.test}}"} | ||
); | ||
|
||
report "[20]: nested dict cast to string"; | ||
report djson.parse( | ||
{"a": {"test": 1}}, | ||
{"b": "{{$s.a.test}}"} | ||
); | ||
|
||
report "[21]: nested dict partial"; | ||
report djson.parse( | ||
{"a": {"test": 1}}, | ||
{"b": "partial-{{$.a.test}}"} | ||
); | ||
|
||
report "[22]: super nested dict that returns the value"; | ||
report djson.parse( | ||
{"a": {"test": [{ | ||
"a":1, | ||
"b":2, | ||
"c":3 | ||
}]}}, | ||
"{{$.a.test.0.c}}" | ||
); | ||
|
||
report "[23]: string target"; | ||
report djson.parse( | ||
{"a": "1"}, | ||
"{{$.a}}" | ||
); | ||
|
||
report "[24]: string target"; | ||
report djson.parse( | ||
{"a": "1"}, | ||
"{{$.a}}" | ||
); | ||
|
||
report "[25]: string target partial"; | ||
report djson.parse( | ||
{"a": "1"}, | ||
"partial-{{$.a}}" | ||
); | ||
|
||
report "[26]: string source"; | ||
report djson.parse( | ||
"testing", | ||
{"b": "{{$}}"} | ||
); | ||
|
||
report "[27]: string source partial"; | ||
report djson.parse( | ||
"testing", | ||
{"b": "partial-{{$}}"} | ||
); | ||
|
||
report "[28]: int source"; | ||
report djson.parse( | ||
1, | ||
{"b": "{{$}}"} | ||
); | ||
|
||
report "[29]: int source cast"; | ||
report djson.parse( | ||
1, | ||
{"b": "{{$s}}"} | ||
); | ||
|
||
report "[30]: int source partial"; | ||
report djson.parse( | ||
1, | ||
{"b": "partial-{{$}}"} | ||
); | ||
|
||
report "[31]: int source string target"; | ||
report djson.parse( | ||
1, | ||
"{{$}}" | ||
); | ||
|
||
report "[32]: int source string target cast"; | ||
report djson.parse( | ||
1, | ||
"{{$s}}" | ||
); | ||
|
||
report "[33]: not existing"; | ||
report djson.parse( | ||
{"a": {"b": 1}}, | ||
{"b": "{{$.a.c}}"} | ||
); | ||
|
||
report "[34]: not existing cast to string empty"; | ||
report djson.parse( | ||
{"a": {"b": 1}}, | ||
{"b": "{{$s.a.c}}"} | ||
); | ||
|
||
report "[35]: string source cast to dict"; | ||
report djson.parse( | ||
"{}", | ||
"{{$d}}" | ||
); | ||
|
||
report "[36]: string source cast to int"; | ||
report djson.parse( | ||
"1", | ||
"{{$i}}" | ||
); | ||
} | ||
} |
Oops, something went wrong.