oocana-python-executor 0.16.13__tar.gz → 0.16.14__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/PKG-INFO +1 -1
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/pyproject.toml +1 -1
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/context.py +3 -0
- oocana_python_executor-0.16.14/python_executor/credential.py +43 -0
- oocana_python_executor-0.16.14/tests/test_credential.py +102 -0
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/__init__.py +0 -0
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/block.py +0 -0
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/data.py +0 -0
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/executor.py +0 -0
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/hook.py +0 -0
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/logger.py +0 -0
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/matplot/matplotlib_oomol/__init__.py +0 -0
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/matplot/matplotlib_oomol/oomol.py +0 -0
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/matplot/oomol_matplot_helper.py +0 -0
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/secret.py +0 -0
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/service.py +0 -0
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/topic.py +0 -0
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/utils.py +0 -0
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/tests/test_cli.py +0 -0
- {oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/tests/test_secret.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: oocana-python-executor
|
|
3
|
-
Version: 0.16.
|
|
3
|
+
Version: 0.16.14
|
|
4
4
|
Summary: a client subscribe mqtt topic to execute oocana's block
|
|
5
5
|
Author-Email: l1shen <lishen1635@gmail.com>, yleaf <11785335+leavesster@users.noreply.github.com>
|
|
6
6
|
License: MIT
|
{oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/context.py
RENAMED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
|
|
3
|
+
from .credential import replace_credential
|
|
2
4
|
from oocana import Mainframe, Context, StoreKey, BlockInfo, BinValueDict, VarValueDict, InputHandleDef, is_bin_value, is_var_value
|
|
3
5
|
from typing import Dict
|
|
4
6
|
from .secret import replace_secret
|
|
@@ -24,6 +26,7 @@ def createContext(
|
|
|
24
26
|
inputs_def_handles[k] = InputHandleDef(**v)
|
|
25
27
|
|
|
26
28
|
inputs = replace_secret(inputs, inputs_def_handles, node_props.get("inputs_def_patch"))
|
|
29
|
+
inputs = replace_credential(inputs, inputs_def_handles)
|
|
27
30
|
|
|
28
31
|
for k, v in inputs.items():
|
|
29
32
|
input_def = inputs_def_handles.get(k)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
from oocana import InputHandleDef
|
|
3
|
+
class CredentialInput:
|
|
4
|
+
def __init__(self, type: str, value: str):
|
|
5
|
+
self.type = type
|
|
6
|
+
self.value = value
|
|
7
|
+
|
|
8
|
+
def generate_credential_input(credential_path: str) -> CredentialInput | None:
|
|
9
|
+
"""Generate a CredentialInput from a credential path string.
|
|
10
|
+
|
|
11
|
+
The credential path should be in the format `${{OO_CREDENTIAL:type,id}}`. If the format is incorrect,
|
|
12
|
+
the function returns None.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
if not (credential_path.startswith("${{OO_CREDENTIAL:") and credential_path.endswith("}}")):
|
|
16
|
+
return None
|
|
17
|
+
|
|
18
|
+
credential_path = credential_path.removeprefix("${{OO_CREDENTIAL:").removesuffix("}}")
|
|
19
|
+
if credential_path:
|
|
20
|
+
try:
|
|
21
|
+
type, id = credential_path.split(",", maxsplit=1)
|
|
22
|
+
return CredentialInput(type, id)
|
|
23
|
+
except ValueError:
|
|
24
|
+
return None
|
|
25
|
+
return None
|
|
26
|
+
|
|
27
|
+
def replace_credential(
|
|
28
|
+
inputs: Any,
|
|
29
|
+
input_def: Dict[str, InputHandleDef] | None = None,
|
|
30
|
+
) -> Any:
|
|
31
|
+
if not isinstance(inputs, dict):
|
|
32
|
+
return inputs
|
|
33
|
+
|
|
34
|
+
assert isinstance(inputs, dict)
|
|
35
|
+
|
|
36
|
+
for k, v in inputs.items():
|
|
37
|
+
current_input_def = input_def.get(k) if input_def else None
|
|
38
|
+
if current_input_def is None:
|
|
39
|
+
continue
|
|
40
|
+
if isinstance(v, str) and current_input_def.is_credential_handle():
|
|
41
|
+
cred_input = generate_credential_input(v)
|
|
42
|
+
inputs[k] = cred_input
|
|
43
|
+
return inputs
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from python_executor.credential import replace_credential, CredentialInput, generate_credential_input
|
|
3
|
+
from oocana import InputHandleDef
|
|
4
|
+
from typing import cast
|
|
5
|
+
|
|
6
|
+
ORIGIN_VALUE = "Custom,credential_id"
|
|
7
|
+
|
|
8
|
+
class TestCredential(unittest.TestCase):
|
|
9
|
+
|
|
10
|
+
def test_credential_fallback(self):
|
|
11
|
+
"""Test credential fallback when not a credential handle"""
|
|
12
|
+
v = replace_credential({
|
|
13
|
+
"c": "aaaa"
|
|
14
|
+
}, {
|
|
15
|
+
"c": InputHandleDef(handle="c", json_schema={
|
|
16
|
+
"contentMediaType": "oomol/credential"
|
|
17
|
+
}, value=None)
|
|
18
|
+
})
|
|
19
|
+
# Should return CredentialInput when parsed successfully
|
|
20
|
+
cred_input = generate_credential_input("aaaa")
|
|
21
|
+
self.assertIsNone(cred_input)
|
|
22
|
+
self.assertIsNone(v.get("c"))
|
|
23
|
+
|
|
24
|
+
def test_replace_credential(self):
|
|
25
|
+
"""Test basic credential replacement"""
|
|
26
|
+
v = replace_credential({
|
|
27
|
+
"c": f'${{{{OO_CREDENTIAL:{ORIGIN_VALUE}}}}}'
|
|
28
|
+
}, {
|
|
29
|
+
"c": InputHandleDef(handle="c", json_schema={
|
|
30
|
+
"contentMediaType": "oomol/credential"
|
|
31
|
+
}, value=None)
|
|
32
|
+
})
|
|
33
|
+
cred_input = v.get("c")
|
|
34
|
+
self.assertIsInstance(cred_input, CredentialInput)
|
|
35
|
+
self.assertEqual(cred_input.type, "Custom")
|
|
36
|
+
self.assertEqual(cred_input.value, "credential_id")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_credential_without_content_media(self):
|
|
40
|
+
"""Test multiple credentials replacement"""
|
|
41
|
+
v = replace_credential({
|
|
42
|
+
"c": f'${{{{OO_CREDENTIAL:{ORIGIN_VALUE}}}}}',
|
|
43
|
+
"a": f'${{{{OO_CREDENTIAL:{ORIGIN_VALUE}}}}}'
|
|
44
|
+
}, {
|
|
45
|
+
"c": InputHandleDef(handle="c", json_schema={
|
|
46
|
+
"contentMediaType": "oomol/credential"
|
|
47
|
+
}, value=None)
|
|
48
|
+
})
|
|
49
|
+
cred_input_c = v.get("c")
|
|
50
|
+
cred_input_a = v.get("a")
|
|
51
|
+
|
|
52
|
+
self.assertIsInstance(cred_input_c, CredentialInput)
|
|
53
|
+
self.assertEqual(cred_input_c.type, "Custom")
|
|
54
|
+
|
|
55
|
+
# 'a' should remain unchanged since no input_def for it
|
|
56
|
+
self.assertEqual(cred_input_a, f'${{{{OO_CREDENTIAL:{ORIGIN_VALUE}}}}}')
|
|
57
|
+
|
|
58
|
+
def test_credential_in_other_string(self):
|
|
59
|
+
"""Test credential pattern inside other string (should not be replaced)"""
|
|
60
|
+
no_replace_value = f'${{{{OO_CREDENTIAL:{ORIGIN_VALUE}}}}}_bbb'
|
|
61
|
+
v = replace_credential({
|
|
62
|
+
"c": no_replace_value
|
|
63
|
+
}, {
|
|
64
|
+
"c": InputHandleDef(handle="c", json_schema={
|
|
65
|
+
"contentMediaType": "oomol/credential"
|
|
66
|
+
}, value=None)
|
|
67
|
+
})
|
|
68
|
+
# Should not be replaced because it doesn't match exact format
|
|
69
|
+
self.assertEqual(v.get("c"), None)
|
|
70
|
+
|
|
71
|
+
def test_generate_credential_input_valid(self):
|
|
72
|
+
"""Test valid credential input generation"""
|
|
73
|
+
result = generate_credential_input("${{OO_CREDENTIAL:AWS,my_credential_id}}")
|
|
74
|
+
self.assertIsInstance(result, CredentialInput)
|
|
75
|
+
result = cast(CredentialInput, result)
|
|
76
|
+
self.assertEqual(result.type, "AWS")
|
|
77
|
+
self.assertEqual(result.value, "my_credential_id")
|
|
78
|
+
|
|
79
|
+
def test_generate_credential_input_invalid_format(self):
|
|
80
|
+
"""Test invalid credential input format"""
|
|
81
|
+
# Missing prefix
|
|
82
|
+
result = generate_credential_input("AWS,my_credential_id")
|
|
83
|
+
self.assertIsNone(result)
|
|
84
|
+
|
|
85
|
+
# Missing suffix
|
|
86
|
+
result = generate_credential_input("${{OO_CREDENTIAL:AWS,my_credential_id")
|
|
87
|
+
self.assertIsNone(result)
|
|
88
|
+
|
|
89
|
+
# Wrong prefix
|
|
90
|
+
result = generate_credential_input("${{OO_SECRET:AWS,my_credential_id}}")
|
|
91
|
+
self.assertIsNone(result)
|
|
92
|
+
|
|
93
|
+
# Empty content
|
|
94
|
+
result = generate_credential_input("${{OO_CREDENTIAL:}}")
|
|
95
|
+
self.assertIsNone(result)
|
|
96
|
+
|
|
97
|
+
# Missing comma
|
|
98
|
+
result = generate_credential_input("${{OO_CREDENTIAL:AWS}}")
|
|
99
|
+
self.assertIsNone(result)
|
|
100
|
+
|
|
101
|
+
if __name__ == '__main__':
|
|
102
|
+
unittest.main()
|
{oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/executor.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{oocana_python_executor-0.16.13 → oocana_python_executor-0.16.14}/python_executor/service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|