dshellInterpreter 1.2.1.0__tar.gz → 1.2.1.2__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.
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_ui.py +91 -73
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellInterpreteur/dshell_interpreter.py +12 -5
- dshellinterpreter-1.2.1.2/Dshell/DshellInterpreteur/dshell_scope.py +159 -0
- {dshellinterpreter-1.2.1.0/dshellInterpreter.egg-info → dshellinterpreter-1.2.1.2}/PKG-INFO +1 -1
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2/dshellInterpreter.egg-info}/PKG-INFO +1 -1
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/setup.py +1 -1
- dshellinterpreter-1.2.1.0/Dshell/DshellInterpreteur/dshell_scope.py +0 -81
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/__init__.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_channel.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_embed.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_file.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_interaction.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_member.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_message.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_pastbin.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_role.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/utils/__init__.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/utils/utils_embed.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/utils/utils_file.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/utils/utils_global.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/utils/utils_list.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/utils/utils_member.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/utils/utils_message.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/utils/utils_numbers.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/utils/utils_permissions.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/utils/utils_string.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/utils/utils_thread.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/utils/utils_type_validation.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellInterpreteur/__init__.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellInterpreteur/cached_messages.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellInterpreteur/dshell_arguments.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellInterpreteur/dshell_global_variables.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellInterpreteur/errors.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellInterpreteur/utils_interpreter.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellParser/__init__.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellParser/ast_nodes.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellParser/dshell_parser.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellParser/errors.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellPreProcess/__init__.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellPreProcess/dshell_preprocess.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellTokenizer/__init__.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellTokenizer/dshell_keywords.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellTokenizer/dshell_token_type.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellTokenizer/dshell_tokenizer.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/__init__.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/full_import.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/regex_test.py +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/LICENSE +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/README.md +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/dshellInterpreter.egg-info/SOURCES.txt +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/dshellInterpreter.egg-info/dependency_links.txt +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/dshellInterpreter.egg-info/requires.txt +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/dshellInterpreter.egg-info/top_level.txt +0 -0
- {dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/setup.cfg +0 -0
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_ui.py
RENAMED
|
@@ -13,19 +13,24 @@ from ..DshellParser.ast_nodes import UiSelectNode, UiButtonNode, OptionUiSelectN
|
|
|
13
13
|
|
|
14
14
|
from ..DshellInterpreteur.utils_interpreter import regroupe_commandes
|
|
15
15
|
|
|
16
|
-
from ..DshellInterpreteur.dshell_scope import new_scope
|
|
16
|
+
from ..DshellInterpreteur.dshell_scope import new_scope, get_scope, update_nbr_usage_scope, get_usage_scope
|
|
17
17
|
|
|
18
|
-
from Dshell.full_import import Any, TYPE_CHECKING, Union
|
|
18
|
+
from Dshell.full_import import Any, TYPE_CHECKING, Union, Optional
|
|
19
19
|
|
|
20
20
|
from .utils.utils_type_validation import (_validate_optional_code_node,
|
|
21
|
+
_validate_required_int,
|
|
21
22
|
_validate_optional_int,
|
|
22
|
-
_validate_optional_string
|
|
23
|
+
_validate_optional_string,
|
|
24
|
+
_validate_required_string,
|
|
25
|
+
_validate_required_bool,
|
|
26
|
+
_validate_missing_or_type)
|
|
23
27
|
|
|
24
28
|
from .utils.utils_global import utils_refactor_emoji
|
|
25
29
|
|
|
26
30
|
if TYPE_CHECKING:
|
|
27
31
|
from ..DshellInterpreteur.dshell_interpreter import DshellInterpreteur
|
|
28
32
|
|
|
33
|
+
scope_id = "scope_id"
|
|
29
34
|
|
|
30
35
|
ButtonStyleValues: set = {i.name for i in ButtonStyle}
|
|
31
36
|
SelectSyleValues: dict = {'string': ComponentType.string_select,
|
|
@@ -42,19 +47,22 @@ async def build_ui_button_parameters(ui_button_node: UiButtonNode, interpreter:
|
|
|
42
47
|
:param interpreter:
|
|
43
48
|
:return:
|
|
44
49
|
"""
|
|
50
|
+
_CMD = "button"
|
|
51
|
+
|
|
45
52
|
regrouped_parameters = await regroupe_commandes(ui_button_node.body, interpreter, normalise=True)
|
|
46
53
|
args_button: dict[str, list[Any]] = regrouped_parameters.get_dict_parameters()
|
|
47
54
|
|
|
48
55
|
code = args_button.pop('code', None)
|
|
49
|
-
style = args_button.pop('style', 'primary').lower()
|
|
50
|
-
custom_id = args_button.pop('custom_id', 'ui_button_'+str(random()))
|
|
51
|
-
row = args_button.pop('row', 0)
|
|
56
|
+
style = args_button.pop('style', StrNode('primary')).lower()
|
|
57
|
+
custom_id = args_button.pop('custom_id', StrNode('ui_button_'+str(random())))
|
|
58
|
+
row = args_button.pop('row', IntNode(0))
|
|
52
59
|
emoji = utils_refactor_emoji(args_button.pop('emoji', None))
|
|
53
60
|
|
|
54
|
-
_validate_optional_code_node(code, "
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
_validate_optional_code_node(code, "code", _CMD)
|
|
62
|
+
_validate_required_string(style, "style", _CMD)
|
|
63
|
+
_validate_required_string(custom_id, "custom_id", _CMD)
|
|
64
|
+
_validate_required_int(row, "row", _CMD)
|
|
65
|
+
_validate_optional_string(emoji, "emoji", _CMD)
|
|
58
66
|
|
|
59
67
|
if style not in ButtonStyleValues:
|
|
60
68
|
raise ValueError(f"Button style must be one of {', '.join(ButtonStyleValues)}, not '{style}' !")
|
|
@@ -74,40 +82,32 @@ async def build_ui_select_parameters(ui_select_node: UiSelectNode, interpreter:
|
|
|
74
82
|
:param interpreter:
|
|
75
83
|
:return:
|
|
76
84
|
"""
|
|
85
|
+
_CMD = "select"
|
|
86
|
+
|
|
77
87
|
regrouped_parameters = await regroupe_commandes(ui_select_node.body, interpreter, normalise=True)
|
|
78
88
|
args_select: dict[str, list[Any]] = regrouped_parameters.get_dict_parameters()
|
|
79
89
|
|
|
80
90
|
code = args_select.pop('code', None)
|
|
81
|
-
custom_id = args_select.pop('custom_id', 'ui_select_'+str(random()))
|
|
82
|
-
select_type = args_select.pop('type', 'string').lower()
|
|
83
|
-
|
|
84
|
-
disabled = args_select.get('disabled',
|
|
85
|
-
max_values = args_select.get('max', 1)
|
|
86
|
-
min_values = args_select.get('min', 1)
|
|
87
|
-
placeholder = args_select.get('placeholder', "")
|
|
88
|
-
row = args_select.pop('row', 0)
|
|
89
|
-
|
|
90
|
-
_validate_optional_code_node(code, "Select code",
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if not isinstance(max_values, int):
|
|
102
|
-
raise TypeError(f"Select max_values must be an int, not {type(max_values)} !")
|
|
103
|
-
|
|
104
|
-
if not isinstance(min_values, int):
|
|
105
|
-
raise TypeError(f"Select min_values must be an int, not {type(min_values)} !")
|
|
106
|
-
|
|
107
|
-
if not isinstance(placeholder, str):
|
|
108
|
-
raise TypeError(f"Select placeholder must be a string, not {type(placeholder)} !")
|
|
109
|
-
|
|
110
|
-
_validate_optional_int(row, "Select row", "build_ui_select")
|
|
91
|
+
custom_id = args_select.pop('custom_id', StrNode('ui_select_'+str(random())))
|
|
92
|
+
select_type = args_select.pop('type', StrNode('string')).lower()
|
|
93
|
+
|
|
94
|
+
disabled = args_select.get('disabled', BoolNode(0))
|
|
95
|
+
max_values = args_select.get('max', IntNode(1))
|
|
96
|
+
min_values = args_select.get('min', IntNode(1))
|
|
97
|
+
placeholder = args_select.get('placeholder', StrNode(""))
|
|
98
|
+
row = args_select.pop('row', IntNode(0))
|
|
99
|
+
|
|
100
|
+
_validate_optional_code_node(code, "Select code", _CMD)
|
|
101
|
+
_validate_required_string(custom_id, "custom_id", _CMD)
|
|
102
|
+
_validate_required_string(select_type, "type", _CMD)
|
|
103
|
+
_validate_required_bool(disabled, "disabled", _CMD)
|
|
104
|
+
_validate_required_int(max_values, "max", _CMD)
|
|
105
|
+
_validate_required_int(max_values, "min", _CMD)
|
|
106
|
+
_validate_required_string(placeholder, "placeholder", _CMD)
|
|
107
|
+
_validate_optional_int(row, "row", _CMD)
|
|
108
|
+
|
|
109
|
+
if select_type not in SelectSyleValues:
|
|
110
|
+
raise TypeError(f"Select style must be one of {', '.join(SelectSyleValues.keys())}, not '{select_type}' !")
|
|
111
111
|
|
|
112
112
|
args_select["disabled"] = disabled
|
|
113
113
|
args_select["max_values"] = max_values
|
|
@@ -128,6 +128,8 @@ async def build_ui_select_options(option_nodes: list[OptionUiSelectNode], interp
|
|
|
128
128
|
:param interpreter:
|
|
129
129
|
:return:
|
|
130
130
|
"""
|
|
131
|
+
_CMD = "option"
|
|
132
|
+
|
|
131
133
|
option_results: list[dict[str, Any]] = []
|
|
132
134
|
|
|
133
135
|
for option_node in option_nodes:
|
|
@@ -140,28 +142,21 @@ async def build_ui_select_options(option_nodes: list[OptionUiSelectNode], interp
|
|
|
140
142
|
emoji = utils_refactor_emoji(args_option.pop('emoji', None))
|
|
141
143
|
default = args_option.pop('default', False)
|
|
142
144
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
+
_validate_required_string(label, "label", _CMD)
|
|
146
|
+
_validate_missing_or_type(value, "value", StrNode, _CMD)
|
|
147
|
+
_validate_optional_string(description, "description", _CMD)
|
|
148
|
+
_validate_optional_string(emoji, "emoji", _CMD)
|
|
149
|
+
_validate_required_bool(default, "default", _CMD)
|
|
145
150
|
|
|
146
151
|
if len(label) > 100:
|
|
147
152
|
raise ValueError("Option label must be less than 100 characters !")
|
|
148
153
|
|
|
149
|
-
if value and not isinstance(value, str):
|
|
150
|
-
raise TypeError(f"Option value must be a string, not {type(value)} !")
|
|
151
|
-
|
|
152
154
|
if value and len(value) > 100:
|
|
153
155
|
raise ValueError("Option value must be less than 100 characters !")
|
|
154
156
|
|
|
155
|
-
_validate_optional_string(description, "Option description", "build_ui_option")
|
|
156
|
-
|
|
157
157
|
if description is not None and len(description) > 100:
|
|
158
158
|
raise ValueError("Option description must be less than 100 characters !")
|
|
159
159
|
|
|
160
|
-
_validate_optional_string(emoji, "Option emoji", "build_ui_option")
|
|
161
|
-
|
|
162
|
-
if not isinstance(default, bool):
|
|
163
|
-
raise TypeError(f"Option default must be a bool, not {type(default)} !")
|
|
164
|
-
|
|
165
160
|
option_dict = {
|
|
166
161
|
'label': label,
|
|
167
162
|
'value': value,
|
|
@@ -186,10 +181,9 @@ async def build_ui(ui_node: Union[UiButtonNode, UiSelectNode], interpreter: "Dsh
|
|
|
186
181
|
|
|
187
182
|
if isinstance(ui_node, UiButtonNode):
|
|
188
183
|
async for _, args_button, code in build_ui_button_parameters(ui_node, interpreter):
|
|
189
|
-
print(args_button)
|
|
190
184
|
b = ui.Button(**args_button)
|
|
191
185
|
view.add_items(b)
|
|
192
|
-
view.set_callable(b.custom_id, _callable=ui_button_callback, data={'code': code,
|
|
186
|
+
view.set_callable(b.custom_id, _callable=ui_button_callback, data={'code': code, scope_id: interpreter.scope_id})
|
|
193
187
|
|
|
194
188
|
elif isinstance(ui_node, UiSelectNode):
|
|
195
189
|
s = SelectMenu()
|
|
@@ -204,23 +198,23 @@ async def build_ui(ui_node: Union[UiButtonNode, UiSelectNode], interpreter: "Dsh
|
|
|
204
198
|
for option in options:
|
|
205
199
|
menu.add_option(**option)
|
|
206
200
|
|
|
207
|
-
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code,
|
|
201
|
+
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, scope_id: interpreter.scope_id})
|
|
208
202
|
|
|
209
203
|
elif select_type == ComponentType.role_select:
|
|
210
204
|
s.add_role_select_menu(**args_select)
|
|
211
|
-
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code,
|
|
205
|
+
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, scope_id: interpreter.scope_id})
|
|
212
206
|
|
|
213
207
|
elif select_type == ComponentType.user_select:
|
|
214
208
|
s.add_user_select_menu(**args_select)
|
|
215
|
-
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code,
|
|
209
|
+
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, scope_id: interpreter.scope_id})
|
|
216
210
|
|
|
217
211
|
elif select_type == ComponentType.mentionable_select:
|
|
218
212
|
s.add_mentionable_select_menu(**args_select)
|
|
219
|
-
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code,
|
|
213
|
+
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, scope_id: interpreter.scope_id})
|
|
220
214
|
|
|
221
215
|
elif select_type == ComponentType.channel_select:
|
|
222
216
|
s.add_channel_select_menu(**args_select)
|
|
223
|
-
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code,
|
|
217
|
+
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, scope_id: interpreter.scope_id})
|
|
224
218
|
|
|
225
219
|
view.add_items(s)
|
|
226
220
|
|
|
@@ -253,7 +247,7 @@ async def rebuild_ui(ui_node: Union[UiButtonNode, UiSelectNode], view: EasyModif
|
|
|
253
247
|
ui.url = args_button.get('url', ui.url)
|
|
254
248
|
ui.row = args_button.get('row', ui.row)
|
|
255
249
|
new_code = code if code is not None else view.get_callable_data(args_button['custom_id'])['code']
|
|
256
|
-
view.set_callable(args_button['custom_id'], _callable=ui_button_callback, data={'code': new_code,
|
|
250
|
+
view.set_callable(args_button['custom_id'], _callable=ui_button_callback, data={'code': new_code, scope_id: interpreter.scope_id})
|
|
257
251
|
|
|
258
252
|
elif isinstance(ui_node, UiSelectNode):
|
|
259
253
|
|
|
@@ -274,7 +268,7 @@ async def rebuild_ui(ui_node: Union[UiButtonNode, UiSelectNode], view: EasyModif
|
|
|
274
268
|
ui.add_option(**option)
|
|
275
269
|
|
|
276
270
|
new_code = code if code is not None else view.get_callable_data(args_select['custom_id'])['code']
|
|
277
|
-
view.set_callable(args_select['custom_id'], _callable=ui_select_callback, data={'code': new_code,
|
|
271
|
+
view.set_callable(args_select['custom_id'], _callable=ui_select_callback, data={'code': new_code, scope_id: interpreter.scope_id})
|
|
278
272
|
|
|
279
273
|
return view
|
|
280
274
|
|
|
@@ -288,8 +282,9 @@ async def ui_button_callback(button: ui.Button, interaction: Interaction, data:
|
|
|
288
282
|
:param data:
|
|
289
283
|
:return:
|
|
290
284
|
"""
|
|
291
|
-
code = data.
|
|
292
|
-
|
|
285
|
+
code = data.get('code', None)
|
|
286
|
+
scope: Optional[str] = data.get(scope_id, None)
|
|
287
|
+
|
|
293
288
|
if code is not None:
|
|
294
289
|
message = interaction
|
|
295
290
|
local_env = {
|
|
@@ -377,14 +372,26 @@ async def ui_button_callback(button: ui.Button, interaction: Interaction, data:
|
|
|
377
372
|
}
|
|
378
373
|
)
|
|
379
374
|
|
|
380
|
-
local_env.update(data)
|
|
381
375
|
from ..DshellInterpreteur.dshell_interpreter import DshellInterpreteur
|
|
382
|
-
|
|
383
|
-
|
|
376
|
+
|
|
377
|
+
new_interpreter = DshellInterpreteur(
|
|
378
|
+
code,
|
|
379
|
+
ctx=interaction,
|
|
380
|
+
debug=False,
|
|
381
|
+
vars_env=get_scope(scope))
|
|
382
|
+
|
|
383
|
+
if scope is not None:
|
|
384
|
+
update_nbr_usage_scope(scope, 1)
|
|
385
|
+
|
|
386
|
+
with new_scope(new_interpreter, local_env):
|
|
387
|
+
await new_interpreter.execute()
|
|
388
|
+
|
|
389
|
+
if scope is not None:
|
|
390
|
+
update_nbr_usage_scope(scope, -1)
|
|
391
|
+
|
|
384
392
|
else:
|
|
385
393
|
await interaction.response.defer(invisible=True)
|
|
386
394
|
|
|
387
|
-
data.update({'code': code, 'interpreter': interpreter})
|
|
388
395
|
|
|
389
396
|
async def ui_select_callback(select: ui.Select, interaction: Interaction, data: dict[str, Any]):
|
|
390
397
|
"""
|
|
@@ -395,8 +402,8 @@ async def ui_select_callback(select: ui.Select, interaction: Interaction, data:
|
|
|
395
402
|
:param data:
|
|
396
403
|
:return:
|
|
397
404
|
"""
|
|
398
|
-
code = data.
|
|
399
|
-
|
|
405
|
+
code = data.get('code', None)
|
|
406
|
+
scope: Optional[str] = data.get(scope_id, None)
|
|
400
407
|
|
|
401
408
|
message = interaction
|
|
402
409
|
if code is not None:
|
|
@@ -511,9 +518,20 @@ async def ui_select_callback(select: ui.Select, interaction: Interaction, data:
|
|
|
511
518
|
|
|
512
519
|
local_env.update(data)
|
|
513
520
|
from ..DshellInterpreteur.dshell_interpreter import DshellInterpreteur
|
|
514
|
-
|
|
515
|
-
|
|
521
|
+
new_interpreter = DshellInterpreteur(
|
|
522
|
+
code,
|
|
523
|
+
ctx=interaction,
|
|
524
|
+
debug=False,
|
|
525
|
+
vars_env=get_scope(scope))
|
|
526
|
+
|
|
527
|
+
if scope is not None:
|
|
528
|
+
update_nbr_usage_scope(scope, 1)
|
|
529
|
+
|
|
530
|
+
with new_scope(new_interpreter, local_env):
|
|
531
|
+
await new_interpreter.execute()
|
|
532
|
+
|
|
533
|
+
if scope is not None:
|
|
534
|
+
update_nbr_usage_scope(scope, -1)
|
|
535
|
+
|
|
516
536
|
else:
|
|
517
537
|
await interaction.response.defer(invisible=True)
|
|
518
|
-
|
|
519
|
-
data.update({'code': code, 'interpreter': interpreter})
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
from ..DshellTokenizer.dshell_token_type import Token
|
|
2
2
|
from ..DshellTokenizer.dshell_token_type import DshellTokenType as DTT
|
|
3
|
-
from ..
|
|
4
|
-
from Dshell.full_import import TypeVar, Union, Optional, Any, Callable, sleep, findall
|
|
3
|
+
from ..full_import import TypeVar, Union, Optional, Any, Callable, sleep, findall
|
|
5
4
|
from ..DshellParser.ast_nodes import *
|
|
6
|
-
from
|
|
5
|
+
from ..full_import import AutoShardedBot, Interaction, Message, PrivateChannel, random
|
|
7
6
|
from ..DshellParser.dshell_parser import parse, print_ast
|
|
8
7
|
from ..DshellTokenizer.dshell_tokenizer import DshellTokenizer
|
|
9
8
|
from .cached_messages import dshell_cached_messages
|
|
@@ -12,7 +11,7 @@ from .utils_interpreter import get_params, eval_expression, eval_expression_inli
|
|
|
12
11
|
from ..DISCORD_COMMANDS.dshell_embed import build_embed, rebuild_embed
|
|
13
12
|
from ..DISCORD_COMMANDS.dshell_ui import build_ui
|
|
14
13
|
from ..DISCORD_COMMANDS.utils.utils_permissions import build_permission
|
|
15
|
-
from .dshell_scope import Scope, new_scope
|
|
14
|
+
from .dshell_scope import Scope, new_scope, get_scope, create_scope, update_nbr_usage_scope, get_usage_scope
|
|
16
15
|
from .dshell_global_variables import MAX_SLEEP_TIME_SECONDS, MIN_SLEEP_TIME_SECONDS
|
|
17
16
|
|
|
18
17
|
|
|
@@ -48,7 +47,14 @@ class DshellInterpreteur:
|
|
|
48
47
|
self.ast: list[ASTNode] = code.body
|
|
49
48
|
|
|
50
49
|
message = ctx.message if isinstance(ctx, Interaction) else ctx
|
|
51
|
-
|
|
50
|
+
|
|
51
|
+
# scope creation
|
|
52
|
+
self.scope_id: str = create_scope()
|
|
53
|
+
self.env: Optional[Scope] = get_scope(self.scope_id)
|
|
54
|
+
|
|
55
|
+
if self.env is None:
|
|
56
|
+
raise Exception(f"Scope {self.scope_id} not found in interpreter creation !")
|
|
57
|
+
|
|
52
58
|
self.env.update({
|
|
53
59
|
'__ret__': None, # environment variables, '__ret__' is used to store the return value of commands
|
|
54
60
|
'__loop__': None, # used to store the current loop variable in loop nodes if the loop identifier is not specified
|
|
@@ -329,6 +335,7 @@ class DshellInterpreteur:
|
|
|
329
335
|
"""
|
|
330
336
|
self.env.clear()
|
|
331
337
|
self.ast.clear()
|
|
338
|
+
update_nbr_usage_scope(self.scope_id, -1)
|
|
332
339
|
|
|
333
340
|
|
|
334
341
|
async def call_function(function: Callable, args: ArgsCommandNode, interpreter: DshellInterpreteur):
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
from contextlib import contextmanager
|
|
2
|
+
from typing import Any, Optional, Dict, Set, Union
|
|
3
|
+
from random import random
|
|
4
|
+
|
|
5
|
+
# manage all scope with one unique ID by scope to separate the interpreter and scopes
|
|
6
|
+
context_scope: dict[str, tuple[int, "Scope"]] = {}
|
|
7
|
+
|
|
8
|
+
def generate_scope_id() -> str:
|
|
9
|
+
"""
|
|
10
|
+
generate a new scope code unused
|
|
11
|
+
:return:
|
|
12
|
+
"""
|
|
13
|
+
while (_id := (str(random()) + str(random()))) in context_scope: pass
|
|
14
|
+
return _id
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_scope(_id: str) -> Union["Scope", None]:
|
|
18
|
+
"""
|
|
19
|
+
Get the current scope linked with an ID
|
|
20
|
+
:param _id:
|
|
21
|
+
:return: the scope link with the id, or None if the scope id is not found
|
|
22
|
+
"""
|
|
23
|
+
x = context_scope.get(_id, None)
|
|
24
|
+
return x[1] if x is not None else x
|
|
25
|
+
|
|
26
|
+
def get_usage_scope(_id: str) -> Union[int, None]:
|
|
27
|
+
"""
|
|
28
|
+
Get the usage number for a scope
|
|
29
|
+
:param _id: An integer, or None if the scope id is not found
|
|
30
|
+
:return:
|
|
31
|
+
"""
|
|
32
|
+
x = context_scope.get(_id, None)
|
|
33
|
+
return x[0] if x is not None else x
|
|
34
|
+
|
|
35
|
+
class Scope:
|
|
36
|
+
"""
|
|
37
|
+
Represents a variable scope with optional parent scope for nested scoping.
|
|
38
|
+
"""
|
|
39
|
+
def __init__(self, parent: Optional[str] = None):
|
|
40
|
+
self.parent: Optional[str] = parent
|
|
41
|
+
self.vars: Dict[str, Any] = {}
|
|
42
|
+
|
|
43
|
+
def get(self, name: str) -> Any:
|
|
44
|
+
"""
|
|
45
|
+
Get a variable value from this scope or parent scopes.
|
|
46
|
+
:param name: Variable name
|
|
47
|
+
:return: Variable value
|
|
48
|
+
:raises KeyError: If variable not found in any scope
|
|
49
|
+
"""
|
|
50
|
+
if name in self.vars:
|
|
51
|
+
return self.vars[name]
|
|
52
|
+
if self.parent:
|
|
53
|
+
if self.parent in context_scope:
|
|
54
|
+
return context_scope[self.parent][1].get(name)
|
|
55
|
+
raise Exception(f"Scope {self.parent} not found [get] !")
|
|
56
|
+
raise KeyError(name)
|
|
57
|
+
|
|
58
|
+
def set(self, name: str, value: Any) -> None:
|
|
59
|
+
"""
|
|
60
|
+
Set a variable in this scope.
|
|
61
|
+
:param name: Variable name
|
|
62
|
+
:param value: Variable value
|
|
63
|
+
"""
|
|
64
|
+
self.vars[name] = value
|
|
65
|
+
|
|
66
|
+
def update(self, mapping: Dict[str, Any]) -> None:
|
|
67
|
+
"""
|
|
68
|
+
Update multiple variables in this scope.
|
|
69
|
+
:param mapping: Dictionary of variable names and values
|
|
70
|
+
"""
|
|
71
|
+
self.vars.update(mapping)
|
|
72
|
+
|
|
73
|
+
def contains(self, name: str) -> bool:
|
|
74
|
+
"""
|
|
75
|
+
Check if a variable exists in this scope or parent scopes.
|
|
76
|
+
:param name: Variable name
|
|
77
|
+
:return: True if variable exists, False otherwise
|
|
78
|
+
"""
|
|
79
|
+
if name in self.vars:
|
|
80
|
+
return True
|
|
81
|
+
if self.parent:
|
|
82
|
+
if self.parent in context_scope:
|
|
83
|
+
return context_scope[self.parent][1].contains(name)
|
|
84
|
+
Exception(f"Scope {self.parent} not found [contains] !")
|
|
85
|
+
return False
|
|
86
|
+
|
|
87
|
+
def keys(self) -> Set[str]:
|
|
88
|
+
"""
|
|
89
|
+
Get all variable names from this scope and parent scopes.
|
|
90
|
+
:return: Set of variable names
|
|
91
|
+
"""
|
|
92
|
+
keys = set(self.vars.keys())
|
|
93
|
+
if self.parent:
|
|
94
|
+
if self.parent in context_scope:
|
|
95
|
+
keys.update(context_scope[self.parent][1].keys())
|
|
96
|
+
else:
|
|
97
|
+
Exception(f"Scope {self.parent} not found [keys] !")
|
|
98
|
+
return keys
|
|
99
|
+
|
|
100
|
+
def clear(self) -> None:
|
|
101
|
+
"""Clear all variables in this scope (does not affect parent)."""
|
|
102
|
+
self.vars.clear()
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def create_scope() -> str:
|
|
106
|
+
"""
|
|
107
|
+
Create a new scope and return the scope code
|
|
108
|
+
:return:
|
|
109
|
+
"""
|
|
110
|
+
_id = generate_scope_id()
|
|
111
|
+
scope = Scope()
|
|
112
|
+
context_scope[_id] = (1, scope)
|
|
113
|
+
return _id
|
|
114
|
+
|
|
115
|
+
def update_nbr_usage_scope(scope_id: str, nbr_usage: int):
|
|
116
|
+
"""
|
|
117
|
+
Update the usage number for a scope
|
|
118
|
+
:param nbr_usage:
|
|
119
|
+
:return:
|
|
120
|
+
"""
|
|
121
|
+
if scope_id not in context_scope:
|
|
122
|
+
raise Exception(f"Scope {scope_id} not found [update nbr usage scope] !")
|
|
123
|
+
|
|
124
|
+
new_usage = get_usage_scope(scope_id)+nbr_usage
|
|
125
|
+
|
|
126
|
+
if new_usage <= 0:
|
|
127
|
+
del context_scope[scope_id]
|
|
128
|
+
return
|
|
129
|
+
|
|
130
|
+
new = (new_usage, context_scope[scope_id][1])
|
|
131
|
+
|
|
132
|
+
del context_scope[scope_id]
|
|
133
|
+
context_scope[scope_id] = new
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@contextmanager
|
|
137
|
+
def new_scope(interpreter, initial_vars: Optional[Dict[str, Any]] = None):
|
|
138
|
+
"""
|
|
139
|
+
Context manager for creating a new scope temporarily.
|
|
140
|
+
:param interpreter: The interpreter instance
|
|
141
|
+
:param initial_vars: Optional initial variables for the new scope
|
|
142
|
+
"""
|
|
143
|
+
parent = interpreter.scope_id
|
|
144
|
+
|
|
145
|
+
new_scope_id: str = generate_scope_id()
|
|
146
|
+
context_scope[new_scope_id] = (1, Scope(parent))
|
|
147
|
+
|
|
148
|
+
interpreter.scope_id = new_scope_id
|
|
149
|
+
interpreter.env = get_scope(new_scope_id)
|
|
150
|
+
|
|
151
|
+
if initial_vars:
|
|
152
|
+
interpreter.env.update(initial_vars)
|
|
153
|
+
try:
|
|
154
|
+
yield
|
|
155
|
+
finally:
|
|
156
|
+
interpreter.clear()
|
|
157
|
+
interpreter.env = get_scope(parent)
|
|
158
|
+
interpreter.scope_id = parent
|
|
159
|
+
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name="dshellInterpreter",
|
|
8
|
-
version="1.2.1.
|
|
8
|
+
version="1.2.1.2",
|
|
9
9
|
author="Chronos",
|
|
10
10
|
author_email="vagabonwalybi@gmail.com",
|
|
11
11
|
description="A Discord bot interpreter for creating custom commands and automations.",
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
from contextlib import contextmanager
|
|
2
|
-
from typing import Any, Optional, Dict, Set
|
|
3
|
-
|
|
4
|
-
class Scope:
|
|
5
|
-
"""
|
|
6
|
-
Represents a variable scope with optional parent scope for nested scoping.
|
|
7
|
-
"""
|
|
8
|
-
def __init__(self, parent: Optional['Scope'] = None):
|
|
9
|
-
self.parent: Optional['Scope'] = parent
|
|
10
|
-
self.vars: Dict[str, Any] = {}
|
|
11
|
-
|
|
12
|
-
def get(self, name: str) -> Any:
|
|
13
|
-
"""
|
|
14
|
-
Get a variable value from this scope or parent scopes.
|
|
15
|
-
:param name: Variable name
|
|
16
|
-
:return: Variable value
|
|
17
|
-
:raises KeyError: If variable not found in any scope
|
|
18
|
-
"""
|
|
19
|
-
if name in self.vars:
|
|
20
|
-
return self.vars[name]
|
|
21
|
-
if self.parent:
|
|
22
|
-
return self.parent.get(name)
|
|
23
|
-
raise KeyError(name)
|
|
24
|
-
|
|
25
|
-
def set(self, name: str, value: Any) -> None:
|
|
26
|
-
"""
|
|
27
|
-
Set a variable in this scope.
|
|
28
|
-
:param name: Variable name
|
|
29
|
-
:param value: Variable value
|
|
30
|
-
"""
|
|
31
|
-
self.vars[name] = value
|
|
32
|
-
|
|
33
|
-
def update(self, mapping: Dict[str, Any]) -> None:
|
|
34
|
-
"""
|
|
35
|
-
Update multiple variables in this scope.
|
|
36
|
-
:param mapping: Dictionary of variable names and values
|
|
37
|
-
"""
|
|
38
|
-
self.vars.update(mapping)
|
|
39
|
-
|
|
40
|
-
def contains(self, name: str) -> bool:
|
|
41
|
-
"""
|
|
42
|
-
Check if a variable exists in this scope or parent scopes.
|
|
43
|
-
:param name: Variable name
|
|
44
|
-
:return: True if variable exists, False otherwise
|
|
45
|
-
"""
|
|
46
|
-
if name in self.vars:
|
|
47
|
-
return True
|
|
48
|
-
if self.parent:
|
|
49
|
-
return self.parent.contains(name)
|
|
50
|
-
return False
|
|
51
|
-
|
|
52
|
-
def keys(self) -> Set[str]:
|
|
53
|
-
"""
|
|
54
|
-
Get all variable names from this scope and parent scopes.
|
|
55
|
-
:return: Set of variable names
|
|
56
|
-
"""
|
|
57
|
-
keys = set(self.vars.keys())
|
|
58
|
-
if self.parent:
|
|
59
|
-
keys.update(self.parent.keys())
|
|
60
|
-
return keys
|
|
61
|
-
|
|
62
|
-
def clear(self) -> None:
|
|
63
|
-
"""Clear all variables in this scope (does not affect parent)."""
|
|
64
|
-
self.vars.clear()
|
|
65
|
-
|
|
66
|
-
@contextmanager
|
|
67
|
-
def new_scope(interpreter, initial_vars: Optional[Dict[str, Any]] = None):
|
|
68
|
-
"""
|
|
69
|
-
Context manager for creating a new scope temporarily.
|
|
70
|
-
:param interpreter: The interpreter instance
|
|
71
|
-
:param initial_vars: Optional initial variables for the new scope
|
|
72
|
-
"""
|
|
73
|
-
parent = interpreter.env
|
|
74
|
-
interpreter.env = Scope(parent)
|
|
75
|
-
if initial_vars:
|
|
76
|
-
interpreter.env.update(initial_vars)
|
|
77
|
-
try:
|
|
78
|
-
yield
|
|
79
|
-
finally:
|
|
80
|
-
interpreter.env.clear()
|
|
81
|
-
interpreter.env = parent
|
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_channel.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_embed.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_file.py
RENAMED
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_member.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_message.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_pastbin.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/dshell_role.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/utils/__init__.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/utils/utils_embed.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/utils/utils_file.py
RENAMED
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DISCORD_COMMANDS/utils/utils_list.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellInterpreteur/__init__.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellInterpreteur/cached_messages.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellParser/dshell_parser.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellPreProcess/dshell_preprocess.py
RENAMED
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellTokenizer/dshell_keywords.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellTokenizer/dshell_token_type.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/Dshell/DshellTokenizer/dshell_tokenizer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/dshellInterpreter.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/dshellInterpreter.egg-info/requires.txt
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.1.0 → dshellinterpreter-1.2.1.2}/dshellInterpreter.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|