dshellInterpreter 1.2.7.10__tar.gz → 1.2.8.0__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.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_ui.py +45 -24
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellInterpreteur/__init__.py +1 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellInterpreteur/dshell_global_variables.py +8 -1
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellInterpreteur/dshell_interpreter.py +6 -12
- dshellinterpreter-1.2.8.0/Dshell/DshellInterpreteur/dshell_scope.py +95 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellParser/ast_nodes.py +53 -31
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellParser/dshell_parser.py +13 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellTokenizer/dshell_keywords.py +1 -1
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellTokenizer/dshell_token_type.py +3 -0
- {dshellinterpreter-1.2.7.10/dshellInterpreter.egg-info → dshellinterpreter-1.2.8.0}/PKG-INFO +1 -1
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0/dshellInterpreter.egg-info}/PKG-INFO +1 -1
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/setup.py +1 -1
- dshellinterpreter-1.2.7.10/Dshell/DshellInterpreteur/dshell_scope.py +0 -159
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/__init__.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_channel.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_embed.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_file.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_interaction.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_member.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_message.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_pastbin.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_role.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/utils/__init__.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/utils/utils_embed.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/utils/utils_file.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/utils/utils_global.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/utils/utils_list.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/utils/utils_member.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/utils/utils_message.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/utils/utils_numbers.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/utils/utils_permissions.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/utils/utils_string.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/utils/utils_thread.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/utils/utils_type_validation.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellInterpreteur/cached_messages.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellInterpreteur/dshell_arguments.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellInterpreteur/dshell_iterators.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellInterpreteur/errors.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellInterpreteur/utils_interpreter.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellParser/__init__.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellParser/errors.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellPreProcess/__init__.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellPreProcess/dshell_preprocess.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellTokenizer/__init__.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellTokenizer/dshell_tokenizer.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/__init__.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/full_import.py +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/LICENSE +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/README.md +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/dshellInterpreter.egg-info/SOURCES.txt +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/dshellInterpreter.egg-info/dependency_links.txt +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/dshellInterpreter.egg-info/requires.txt +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/dshellInterpreter.egg-info/top_level.txt +0 -0
- {dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/setup.cfg +0 -0
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_ui.py
RENAMED
|
@@ -8,13 +8,21 @@ from ..full_import import (ButtonStyle,
|
|
|
8
8
|
SelectMenu,
|
|
9
9
|
ComponentType,
|
|
10
10
|
random,
|
|
11
|
-
IntEnum
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
IntEnum,
|
|
12
|
+
deepcopy)
|
|
13
|
+
|
|
14
|
+
from ..DshellParser.ast_nodes import (UiSelectNode,
|
|
15
|
+
UiButtonNode,
|
|
16
|
+
OptionUiSelectNode,
|
|
17
|
+
CodeNode,
|
|
18
|
+
ListNode,
|
|
19
|
+
StrNode,
|
|
20
|
+
IntNode,
|
|
21
|
+
BoolNode)
|
|
14
22
|
|
|
15
23
|
from ..DshellInterpreteur.utils_interpreter import regroupe_commandes
|
|
16
24
|
|
|
17
|
-
from ..DshellInterpreteur.dshell_scope import new_scope,
|
|
25
|
+
from ..DshellInterpreteur.dshell_scope import new_scope, Scope
|
|
18
26
|
|
|
19
27
|
from ..full_import import Any, TYPE_CHECKING, Union, Optional
|
|
20
28
|
|
|
@@ -31,8 +39,6 @@ from .utils.utils_global import utils_refactor_emoji
|
|
|
31
39
|
if TYPE_CHECKING:
|
|
32
40
|
from ..DshellInterpreteur.dshell_interpreter import DshellInterpreteur
|
|
33
41
|
|
|
34
|
-
scope_id = "scope_id"
|
|
35
|
-
|
|
36
42
|
ButtonStyleValues: set = {i.name for i in ButtonStyle}
|
|
37
43
|
SelectSyleValues: dict = {'string': ComponentType.string_select,
|
|
38
44
|
'role': ComponentType.role_select,
|
|
@@ -56,6 +62,25 @@ def check_timeout(timeout: Union[int, IntNode]):
|
|
|
56
62
|
f"and less or equal than[{UITimeout.max_timeout}]")
|
|
57
63
|
return timeout
|
|
58
64
|
|
|
65
|
+
|
|
66
|
+
def build_ui_scope(env: Scope, code_node: CodeNode):
|
|
67
|
+
"""
|
|
68
|
+
Create a new scope to store only variables used in UI.
|
|
69
|
+
:param code_node:
|
|
70
|
+
:return:
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
new_ui_scope = Scope()
|
|
74
|
+
|
|
75
|
+
if not isinstance(code_node, CodeNode) or code_node.global_env_vars is None:
|
|
76
|
+
return new_ui_scope
|
|
77
|
+
|
|
78
|
+
for token in code_node.global_env_vars.env_variables:
|
|
79
|
+
|
|
80
|
+
new_ui_scope.set(token.value, deepcopy(env.get(token.value, None)))
|
|
81
|
+
|
|
82
|
+
return new_ui_scope
|
|
83
|
+
|
|
59
84
|
async def build_ui_button_parameters(ui_button_node: UiButtonNode, interpreter: "DshellInterpreteur"):
|
|
60
85
|
"""
|
|
61
86
|
Builds the parameters for a UI component from the UiNode.
|
|
@@ -201,18 +226,15 @@ async def build_ui(ui_node: Union[UiButtonNode, UiSelectNode], interpreter: "Dsh
|
|
|
201
226
|
:return:
|
|
202
227
|
"""
|
|
203
228
|
|
|
204
|
-
|
|
205
|
-
update_nbr_usage_scope(interpreter.scope_id, -1)
|
|
206
|
-
|
|
207
|
-
view = EasyModifiedViews(timeout=600, call_on_timeout=ui_timeout, disabled_on_timeout=True)
|
|
229
|
+
view = EasyModifiedViews(timeout=600, disabled_on_timeout=True)
|
|
208
230
|
|
|
209
231
|
if isinstance(ui_node, UiButtonNode):
|
|
210
232
|
async for _, args_button, code in build_ui_button_parameters(ui_node, interpreter):
|
|
233
|
+
code: CodeNode
|
|
211
234
|
view.timeout = args_button.pop('timeout', IntNode(UITimeout.default_timeout))
|
|
212
235
|
b = ui.Button(**args_button)
|
|
213
236
|
view.add_items(b)
|
|
214
|
-
view.set_callable(b.custom_id, _callable=ui_button_callback, data={'code': code,
|
|
215
|
-
update_nbr_usage_scope(interpreter.scope_id, 1)
|
|
237
|
+
view.set_callable(b.custom_id, _callable=ui_button_callback, data={'code': code, 'scope': build_ui_scope(interpreter.env, code)})
|
|
216
238
|
|
|
217
239
|
elif isinstance(ui_node, UiSelectNode):
|
|
218
240
|
s = SelectMenu()
|
|
@@ -228,26 +250,25 @@ async def build_ui(ui_node: Union[UiButtonNode, UiSelectNode], interpreter: "Dsh
|
|
|
228
250
|
for option in options:
|
|
229
251
|
menu.add_option(**option)
|
|
230
252
|
|
|
231
|
-
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code,
|
|
253
|
+
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, "scope": build_ui_scope(interpreter.env, code)})
|
|
232
254
|
|
|
233
255
|
elif select_type == ComponentType.role_select:
|
|
234
256
|
s.add_role_select_menu(**args_select)
|
|
235
|
-
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code,
|
|
257
|
+
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, "scope": build_ui_scope(interpreter.env, code)})
|
|
236
258
|
|
|
237
259
|
elif select_type == ComponentType.user_select:
|
|
238
260
|
s.add_user_select_menu(**args_select)
|
|
239
|
-
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code,
|
|
261
|
+
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, "scope": build_ui_scope(interpreter.env, code)})
|
|
240
262
|
|
|
241
263
|
elif select_type == ComponentType.mentionable_select:
|
|
242
264
|
s.add_mentionable_select_menu(**args_select)
|
|
243
|
-
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code,
|
|
265
|
+
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, "scope": build_ui_scope(interpreter.env, code)})
|
|
244
266
|
|
|
245
267
|
elif select_type == ComponentType.channel_select:
|
|
246
268
|
s.add_channel_select_menu(**args_select)
|
|
247
|
-
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code,
|
|
269
|
+
s.set_callable(args_select["custom_id"], _callable=ui_select_callback, data={'code': code, "scope": build_ui_scope(interpreter.env, code)})
|
|
248
270
|
|
|
249
271
|
view.add_items(s)
|
|
250
|
-
update_nbr_usage_scope(interpreter.scope_id, 1)
|
|
251
272
|
|
|
252
273
|
else:
|
|
253
274
|
raise TypeError(f"UI node must be UiButtonNode or UiSelectNode, not {type(ui_node).__name__} !")
|
|
@@ -276,8 +297,8 @@ async def rebuild_ui(ui_node: Union[UiButtonNode, UiSelectNode], view: EasyModif
|
|
|
276
297
|
ui.disabled = args_button.get('disabled', ui.disabled)
|
|
277
298
|
ui.url = args_button.get('url', ui.url)
|
|
278
299
|
ui.row = args_button.get('row', ui.row)
|
|
279
|
-
new_code = code if code is not None else view.get_callable_data(args_button['custom_id'])['code']
|
|
280
|
-
view.set_callable(args_button['custom_id'], _callable=ui_button_callback, data={'code': new_code,
|
|
300
|
+
new_code: CodeNode = code if code is not None else view.get_callable_data(args_button['custom_id'])['code']
|
|
301
|
+
view.set_callable(args_button['custom_id'], _callable=ui_button_callback, data={'code': new_code, "scope": build_ui_scope(interpreter.env, new_code)})
|
|
281
302
|
|
|
282
303
|
elif isinstance(ui_node, UiSelectNode):
|
|
283
304
|
|
|
@@ -297,8 +318,8 @@ async def rebuild_ui(ui_node: Union[UiButtonNode, UiSelectNode], view: EasyModif
|
|
|
297
318
|
for option in options:
|
|
298
319
|
ui.add_option(**option)
|
|
299
320
|
|
|
300
|
-
new_code = code if code is not None else view.get_callable_data(args_select['custom_id'])['code']
|
|
301
|
-
view.set_callable(args_select['custom_id'], _callable=ui_select_callback, data={'code': new_code,
|
|
321
|
+
new_code: CodeNode = code if code is not None else view.get_callable_data(args_select['custom_id'])['code']
|
|
322
|
+
view.set_callable(args_select['custom_id'], _callable=ui_select_callback, data={'code': new_code, "scope": build_ui_scope(interpreter.env, new_code)})
|
|
302
323
|
|
|
303
324
|
return view
|
|
304
325
|
|
|
@@ -313,7 +334,7 @@ async def ui_button_callback(button: ui.Button, interaction: Interaction, data:
|
|
|
313
334
|
:return:
|
|
314
335
|
"""
|
|
315
336
|
code = data.get('code', None)
|
|
316
|
-
scope: Optional[str] = data.get(
|
|
337
|
+
scope: Optional[str] = data.get("scope", None)
|
|
317
338
|
|
|
318
339
|
if code is not None:
|
|
319
340
|
message = interaction
|
|
@@ -427,7 +448,7 @@ async def ui_select_callback(select: ui.Select, interaction: Interaction, data:
|
|
|
427
448
|
:return:
|
|
428
449
|
"""
|
|
429
450
|
code = data.get('code', None)
|
|
430
|
-
scope: Optional[str] = data.get(
|
|
451
|
+
scope: Optional[str] = data.get("scope", None)
|
|
431
452
|
|
|
432
453
|
message = interaction
|
|
433
454
|
if code is not None:
|
|
@@ -7,4 +7,11 @@ MAX_FILE_SIZE = 1_000_000 # bytes
|
|
|
7
7
|
MAX_SLEEP_TIME_SECONDS = 3_600 # 1 hour
|
|
8
8
|
MIN_SLEEP_TIME_SECONDS = 1
|
|
9
9
|
|
|
10
|
-
MAX_WAIT_MESSAGE_TIMEOUT = 300
|
|
10
|
+
MAX_WAIT_MESSAGE_TIMEOUT = 300
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Nothing:
|
|
14
|
+
"""
|
|
15
|
+
Do nothing.
|
|
16
|
+
Used if None is a usable value.
|
|
17
|
+
"""
|
|
@@ -11,7 +11,7 @@ from .utils_interpreter import get_params, eval_expression, eval_expression_inli
|
|
|
11
11
|
from ..DISCORD_COMMANDS.dshell_embed import build_embed, rebuild_embed
|
|
12
12
|
from ..DISCORD_COMMANDS.dshell_ui import build_ui
|
|
13
13
|
from ..DISCORD_COMMANDS.utils.utils_permissions import build_permission
|
|
14
|
-
from .dshell_scope import Scope, new_scope
|
|
14
|
+
from .dshell_scope import Scope, new_scope
|
|
15
15
|
from .dshell_global_variables import MAX_SLEEP_TIME_SECONDS, MIN_SLEEP_TIME_SECONDS
|
|
16
16
|
from .dshell_iterators import DshellIterator
|
|
17
17
|
|
|
@@ -50,16 +50,7 @@ class DshellInterpreteur:
|
|
|
50
50
|
message = ctx.message if isinstance(ctx, Interaction) else ctx
|
|
51
51
|
|
|
52
52
|
# scope creation
|
|
53
|
-
|
|
54
|
-
if scope:
|
|
55
|
-
self.env = scope
|
|
56
|
-
self.scope_id = vars_env
|
|
57
|
-
else:
|
|
58
|
-
self.scope_id: str = create_scope()
|
|
59
|
-
self.env: Optional[Scope] = get_scope(self.scope_id)
|
|
60
|
-
|
|
61
|
-
if self.env is None:
|
|
62
|
-
raise Exception(f"Scope {self.scope_id} not found in interpreter creation !")
|
|
53
|
+
self.env: Scope = Scope()
|
|
63
54
|
|
|
64
55
|
self.env.update({
|
|
65
56
|
'__ret__': None, # environment variables, '__ret__' is used to store the return value of commands
|
|
@@ -350,7 +341,10 @@ class DshellInterpreteur:
|
|
|
350
341
|
"""
|
|
351
342
|
Clear the interpreter environment.
|
|
352
343
|
"""
|
|
353
|
-
|
|
344
|
+
self.env.clear()
|
|
345
|
+
del self.env
|
|
346
|
+
self.ast.clear()
|
|
347
|
+
del self.ast
|
|
354
348
|
|
|
355
349
|
|
|
356
350
|
async def call_function(function: Callable, args: ArgsCommandNode, interpreter: DshellInterpreteur):
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
from contextlib import contextmanager
|
|
2
|
+
from typing import Any, Optional, Dict, Set
|
|
3
|
+
from .dshell_global_variables import Nothing
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Scope:
|
|
7
|
+
"""
|
|
8
|
+
Represents a variable scope with optional parent scope for nested scoping.
|
|
9
|
+
"""
|
|
10
|
+
def __init__(self, parent: Optional["Scope"] = None):
|
|
11
|
+
self.parent: Optional[Scope] = parent
|
|
12
|
+
self.vars: Dict[str, Any] = {}
|
|
13
|
+
|
|
14
|
+
def get(self, name: str, default: Any = Nothing()) -> Any:
|
|
15
|
+
"""
|
|
16
|
+
Get a variable value from this scope or parent scopes.
|
|
17
|
+
:param name: Variable name
|
|
18
|
+
:param default: The default variable to return if nothing was found
|
|
19
|
+
:return: Variable value
|
|
20
|
+
:raises KeyError: If variable not found in any scope
|
|
21
|
+
"""
|
|
22
|
+
if name in self.vars:
|
|
23
|
+
return self.vars[name]
|
|
24
|
+
if self.parent:
|
|
25
|
+
return self.parent.get(name)
|
|
26
|
+
if not isinstance(default, Nothing):
|
|
27
|
+
return default
|
|
28
|
+
del default
|
|
29
|
+
raise KeyError(name)
|
|
30
|
+
|
|
31
|
+
def set(self, name: str, value: Any) -> None:
|
|
32
|
+
"""
|
|
33
|
+
Set a variable in this scope.
|
|
34
|
+
:param name: Variable name
|
|
35
|
+
:param value: Variable value
|
|
36
|
+
"""
|
|
37
|
+
self.vars[name] = value
|
|
38
|
+
|
|
39
|
+
def update(self, mapping: Dict[str, Any]) -> None:
|
|
40
|
+
"""
|
|
41
|
+
Update multiple variables in this scope.
|
|
42
|
+
:param mapping: Dictionary of variable names and values
|
|
43
|
+
"""
|
|
44
|
+
self.vars.update(mapping)
|
|
45
|
+
|
|
46
|
+
def contains(self, name: str) -> bool:
|
|
47
|
+
"""
|
|
48
|
+
Check if a variable exists in this scope or parent scopes.
|
|
49
|
+
:param name: Variable name
|
|
50
|
+
:return: True if variable exists, False otherwise
|
|
51
|
+
"""
|
|
52
|
+
if name in self.vars:
|
|
53
|
+
return True
|
|
54
|
+
if self.parent:
|
|
55
|
+
return self.parent.contains(name)
|
|
56
|
+
return False
|
|
57
|
+
|
|
58
|
+
def keys(self) -> Set[str]:
|
|
59
|
+
"""
|
|
60
|
+
Get all variable names from this scope and parent scopes.
|
|
61
|
+
:return: Set of variable names
|
|
62
|
+
"""
|
|
63
|
+
keys = set(self.vars.keys())
|
|
64
|
+
if self.parent:
|
|
65
|
+
keys.update(self.parent.keys())
|
|
66
|
+
return keys
|
|
67
|
+
|
|
68
|
+
def clear(self) -> None:
|
|
69
|
+
"""Clear all variables in this scope (does not affect parent)."""
|
|
70
|
+
self.vars.clear()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@contextmanager
|
|
76
|
+
def new_scope(interpreter, initial_vars: Optional[Dict[str, Any]] = None):
|
|
77
|
+
"""
|
|
78
|
+
Context manager for creating a new scope temporarily.
|
|
79
|
+
:param interpreter: The interpreter instance
|
|
80
|
+
:param initial_vars: Optional initial variables for the new scope
|
|
81
|
+
"""
|
|
82
|
+
parent = interpreter.env
|
|
83
|
+
|
|
84
|
+
new_scope: Scope = Scope(parent=parent)
|
|
85
|
+
|
|
86
|
+
interpreter.env = new_scope
|
|
87
|
+
|
|
88
|
+
if initial_vars:
|
|
89
|
+
interpreter.env.update(initial_vars)
|
|
90
|
+
try:
|
|
91
|
+
yield
|
|
92
|
+
finally:
|
|
93
|
+
interpreter.clear()
|
|
94
|
+
interpreter.env = parent
|
|
95
|
+
|
|
@@ -40,6 +40,7 @@ __all__ = [
|
|
|
40
40
|
'PermissionNode',
|
|
41
41
|
'EvalGroupNode',
|
|
42
42
|
'ParamNode',
|
|
43
|
+
'GlobalNode',
|
|
43
44
|
'CodeNode',
|
|
44
45
|
'EvalNode',
|
|
45
46
|
'ReturnNode',
|
|
@@ -144,52 +145,52 @@ class IntNode(int, ASTNode, DATANode):
|
|
|
144
145
|
return getsizeof(IntNode)
|
|
145
146
|
|
|
146
147
|
def __add__(self, value: "IntNode", /) -> "IntNode":
|
|
147
|
-
if not isinstance(value, IntNode):
|
|
148
|
+
if not isinstance(value, (IntNode, int)):
|
|
148
149
|
raise Exception(f"Cannot add {type(value).__name__} type to IntNode")
|
|
149
150
|
return IntNode(super().__add__(value))
|
|
150
151
|
|
|
151
152
|
def __sub__(self, value: "IntNode", /) -> "IntNode":
|
|
152
|
-
if not isinstance(value, IntNode):
|
|
153
|
+
if not isinstance(value, (IntNode, int)):
|
|
153
154
|
raise Exception(f"Cannot sub {type(value).__name__} type to IntNode")
|
|
154
155
|
return IntNode(super().__sub__(value))
|
|
155
156
|
|
|
156
157
|
def __pow__(self, x: "IntNode", /) -> "IntNode":
|
|
157
|
-
if not isinstance(x, IntNode):
|
|
158
|
+
if not isinstance(x, (IntNode, int)):
|
|
158
159
|
raise Exception(f"Cannot pow {type(x).__name__} type to IntNode")
|
|
159
160
|
return IntNode(super().__pow__(x))
|
|
160
161
|
|
|
161
162
|
def __floordiv__(self, value: "IntNode", /) -> "IntNode":
|
|
162
|
-
if not isinstance(value, IntNode):
|
|
163
|
+
if not isinstance(value, (IntNode, int)):
|
|
163
164
|
raise Exception(f"Cannot divide {type(value).__name__} type to IntNode")
|
|
164
165
|
return IntNode(super().__floordiv__(value))
|
|
165
166
|
|
|
166
167
|
def __rshift__(self, value: "IntNode", /) -> "IntNode":
|
|
167
|
-
if not isinstance(value, IntNode):
|
|
168
|
+
if not isinstance(value, (IntNode, int)):
|
|
168
169
|
raise Exception(f"Cannot shift to the right {type(value).__name__} type to IntNode")
|
|
169
170
|
return IntNode(super().__rshift__(value))
|
|
170
171
|
|
|
171
172
|
def __lshift__(self, value: "IntNode", /) -> "IntNode":
|
|
172
|
-
if not isinstance(value, IntNode):
|
|
173
|
+
if not isinstance(value, (IntNode, int)):
|
|
173
174
|
raise Exception(f"Cannot shift to the left {type(value).__name__} type to IntNode")
|
|
174
175
|
return IntNode(super().__lshift__(value))
|
|
175
176
|
|
|
176
177
|
def __xor__(self, value: "IntNode", /) -> "IntNode":
|
|
177
|
-
if not isinstance(value, IntNode):
|
|
178
|
+
if not isinstance(value, (IntNode, int)):
|
|
178
179
|
raise Exception(f"Cannot xor {type(value).__name__} type to IntNode")
|
|
179
180
|
return IntNode(super().__xor__(value))
|
|
180
181
|
|
|
181
182
|
def __truediv__(self, value: "IntNode", /) -> "FloatNode":
|
|
182
|
-
if not isinstance(value, IntNode):
|
|
183
|
+
if not isinstance(value, (IntNode, int)):
|
|
183
184
|
raise Exception(f"Cannot divide {type(value).__name__} type to IntNode")
|
|
184
185
|
return FloatNode(super().__truediv__(value))
|
|
185
186
|
|
|
186
187
|
def __mul__(self, value: "IntNode", /) -> "IntNode":
|
|
187
|
-
if not isinstance(value, IntNode):
|
|
188
|
+
if not isinstance(value, (IntNode, int)):
|
|
188
189
|
raise Exception(f"Cannot multiply {type(value).__name__} type to IntNode")
|
|
189
190
|
return IntNode(super().__mul__(value))
|
|
190
191
|
|
|
191
192
|
def __mod__(self, value: "IntNode", /) -> "IntNode":
|
|
192
|
-
if not isinstance(value, IntNode):
|
|
193
|
+
if not isinstance(value, (IntNode, int)):
|
|
193
194
|
raise Exception(f"Cannot modulo {type(value).__name__} type to IntNode")
|
|
194
195
|
return IntNode(super().__mod__(value))
|
|
195
196
|
|
|
@@ -205,52 +206,52 @@ class FloatNode(float, ASTNode, DATANode):
|
|
|
205
206
|
return getsizeof(FloatNode)
|
|
206
207
|
|
|
207
208
|
def __add__(self, value: "FloatNode", /) -> "FloatNode":
|
|
208
|
-
if not isinstance(value, FloatNode):
|
|
209
|
+
if not isinstance(value, (FloatNode, float)):
|
|
209
210
|
raise Exception(f"Cannot add {type(value).__name__} type to FloatNode")
|
|
210
211
|
return FloatNode(super().__add__(value))
|
|
211
212
|
|
|
212
213
|
def __sub__(self, value: "FloatNode", /) -> "FloatNode":
|
|
213
|
-
if not isinstance(value, FloatNode):
|
|
214
|
+
if not isinstance(value, (FloatNode, float)):
|
|
214
215
|
raise Exception(f"Cannot sub {type(value).__name__} type to FloatNode")
|
|
215
216
|
return FloatNode(super().__sub__(value))
|
|
216
217
|
|
|
217
218
|
def __pow__(self, x: "FloatNode", /) -> "FloatNode":
|
|
218
|
-
if not isinstance(x, FloatNode):
|
|
219
|
+
if not isinstance(x, (FloatNode, float)):
|
|
219
220
|
raise Exception(f"Cannot pow {type(x).__name__} type to FloatNode")
|
|
220
221
|
return FloatNode(super().__pow__(x))
|
|
221
222
|
|
|
222
223
|
def __floordiv__(self, value: "FloatNode", /) -> "FloatNode":
|
|
223
|
-
if not isinstance(value, FloatNode):
|
|
224
|
+
if not isinstance(value, (FloatNode, float)):
|
|
224
225
|
raise Exception(f"Cannot divide {type(value).__name__} type to FloatNode")
|
|
225
226
|
return FloatNode(super().__floordiv__(value))
|
|
226
227
|
|
|
227
228
|
def __rshift__(self, value: "FloatNode", /) -> "FloatNode":
|
|
228
|
-
if not isinstance(value, FloatNode):
|
|
229
|
+
if not isinstance(value, (FloatNode, float)):
|
|
229
230
|
raise Exception(f"Cannot shift to the right {type(value).__name__} type to FloatNode")
|
|
230
231
|
return FloatNode(super().__rshift__(value))
|
|
231
232
|
|
|
232
233
|
def __lshift__(self, value: "FloatNode", /) -> "FloatNode":
|
|
233
|
-
if not isinstance(value, FloatNode):
|
|
234
|
+
if not isinstance(value, (FloatNode, float)):
|
|
234
235
|
raise Exception(f"Cannot shift to the left {type(value).__name__} type to FloatNode")
|
|
235
236
|
return FloatNode(super().__lshift__(value))
|
|
236
237
|
|
|
237
238
|
def __xor__(self, value: "FloatNode", /) -> "FloatNode":
|
|
238
|
-
if not isinstance(value, FloatNode):
|
|
239
|
+
if not isinstance(value, (FloatNode, float)):
|
|
239
240
|
raise Exception(f"Cannot xor {type(value).__name__} type to FloatNode")
|
|
240
241
|
return FloatNode(super().__xor__(value))
|
|
241
242
|
|
|
242
243
|
def __truediv__(self, value: "FloatNode", /) -> "FloatNode":
|
|
243
|
-
if not isinstance(value, FloatNode):
|
|
244
|
+
if not isinstance(value, (FloatNode, float)):
|
|
244
245
|
raise Exception(f"Cannot divide {type(value).__name__} type to FloatNode")
|
|
245
246
|
return FloatNode(super().__truediv__(value))
|
|
246
247
|
|
|
247
248
|
def __mul__(self, value: "FloatNode", /) -> "FloatNode":
|
|
248
|
-
if not isinstance(value, FloatNode):
|
|
249
|
+
if not isinstance(value, (FloatNode, float)):
|
|
249
250
|
raise Exception(f"Cannot multiply {type(value).__name__} type to FloatNode")
|
|
250
251
|
return FloatNode(super().__mul__(value))
|
|
251
252
|
|
|
252
253
|
def __mod__(self, value: "FloatNode", /) -> "FloatNode":
|
|
253
|
-
if not isinstance(value, FloatNode):
|
|
254
|
+
if not isinstance(value, (FloatNode, float)):
|
|
254
255
|
raise Exception(f"Cannot modulo {type(value).__name__} type to FloatNode")
|
|
255
256
|
return FloatNode(super().__mod__(value))
|
|
256
257
|
|
|
@@ -265,52 +266,52 @@ class BoolNode(int, ASTNode, DATANode):
|
|
|
265
266
|
return getsizeof(BoolNode)
|
|
266
267
|
|
|
267
268
|
def __add__(self, value: Union["BoolNode", "IntNode"], /) -> "BoolNode":
|
|
268
|
-
if not isinstance(value, (BoolNode, IntNode)):
|
|
269
|
+
if not isinstance(value, (BoolNode, IntNode, bool)):
|
|
269
270
|
raise Exception(f"Cannot add {type(value).__name__} type to IntNode")
|
|
270
271
|
return BoolNode(super().__add__(value))
|
|
271
272
|
|
|
272
273
|
def __sub__(self, value: Union["BoolNode", "IntNode"], /) -> "BoolNode":
|
|
273
|
-
if not isinstance(value, (BoolNode, IntNode)):
|
|
274
|
+
if not isinstance(value, (BoolNode, IntNode, bool)):
|
|
274
275
|
raise Exception(f"Cannot sub {type(value).__name__} type to IntNode")
|
|
275
276
|
return BoolNode(super().__sub__(value))
|
|
276
277
|
|
|
277
278
|
def __pow__(self, x: Union["BoolNode", "IntNode"], /) -> "BoolNode":
|
|
278
|
-
if not isinstance(x, (BoolNode, IntNode)):
|
|
279
|
+
if not isinstance(x, (BoolNode, IntNode, bool)):
|
|
279
280
|
raise Exception(f"Cannot pow {type(x).__name__} type to IntNode")
|
|
280
281
|
return BoolNode(super().__pow__(x))
|
|
281
282
|
|
|
282
283
|
def __floordiv__(self, value: Union["BoolNode", "IntNode"], /) -> "BoolNode":
|
|
283
|
-
if not isinstance(value, (BoolNode, IntNode)):
|
|
284
|
+
if not isinstance(value, (BoolNode, IntNode, bool)):
|
|
284
285
|
raise Exception(f"Cannot divide {type(value).__name__} type to IntNode")
|
|
285
286
|
return BoolNode(super().__floordiv__(value))
|
|
286
287
|
|
|
287
288
|
def __rshift__(self, value: Union["BoolNode", "IntNode"], /) -> "BoolNode":
|
|
288
|
-
if not isinstance(value, (BoolNode, IntNode)):
|
|
289
|
+
if not isinstance(value, (BoolNode, IntNode, bool)):
|
|
289
290
|
raise Exception(f"Cannot shift to the right {type(value).__name__} type to IntNode")
|
|
290
291
|
return BoolNode(super().__rshift__(value))
|
|
291
292
|
|
|
292
293
|
def __lshift__(self, value: Union["BoolNode", "IntNode"], /) -> "BoolNode":
|
|
293
|
-
if not isinstance(value, (BoolNode, IntNode)):
|
|
294
|
+
if not isinstance(value, (BoolNode, IntNode, bool)):
|
|
294
295
|
raise Exception(f"Cannot shift to the left {type(value).__name__} type to IntNode")
|
|
295
296
|
return BoolNode(super().__lshift__(value))
|
|
296
297
|
|
|
297
298
|
def __xor__(self, value: Union["BoolNode", "IntNode"], /) -> "BoolNode":
|
|
298
|
-
if not isinstance(value, (BoolNode, IntNode)):
|
|
299
|
+
if not isinstance(value, (BoolNode, IntNode, bool)):
|
|
299
300
|
raise Exception(f"Cannot xor {type(value).__name__} type to IntNode")
|
|
300
301
|
return BoolNode(super().__xor__(value))
|
|
301
302
|
|
|
302
303
|
def __truediv__(self, value: Union["BoolNode", "IntNode"], /) -> "BoolNode":
|
|
303
|
-
if not isinstance(value, (BoolNode, IntNode)):
|
|
304
|
+
if not isinstance(value, (BoolNode, IntNode, bool)):
|
|
304
305
|
raise Exception(f"Cannot divide {type(value).__name__} type to IntNode")
|
|
305
306
|
return BoolNode(super().__truediv__(value))
|
|
306
307
|
|
|
307
308
|
def __mul__(self, value: Union["BoolNode", "IntNode"], /) -> "BoolNode":
|
|
308
|
-
if not isinstance(value, (BoolNode, IntNode)):
|
|
309
|
+
if not isinstance(value, (BoolNode, IntNode, bool)):
|
|
309
310
|
raise Exception(f"Cannot multiply {type(value).__name__} type to IntNode")
|
|
310
311
|
return BoolNode(super().__mul__(value))
|
|
311
312
|
|
|
312
313
|
def __mod__(self, value: Union["BoolNode", "IntNode"], /) -> "BoolNode":
|
|
313
|
-
if not isinstance(value, (BoolNode, IntNode)):
|
|
314
|
+
if not isinstance(value, (BoolNode, IntNode, bool)):
|
|
314
315
|
raise Exception(f"Cannot modulo {type(value).__name__} type to IntNode")
|
|
315
316
|
return BoolNode(super().__mod__(value))
|
|
316
317
|
|
|
@@ -827,16 +828,35 @@ class ParamNode(ASTNode):
|
|
|
827
828
|
"body": [token.to_dict() for token in self.body]
|
|
828
829
|
}
|
|
829
830
|
|
|
831
|
+
|
|
832
|
+
class GlobalNode(ASTNode):
|
|
833
|
+
"""
|
|
834
|
+
Node representing env variables used in code node.
|
|
835
|
+
"""
|
|
836
|
+
def __init__(self, line: int, *args: Token):
|
|
837
|
+
super().__init__(line)
|
|
838
|
+
self.env_variables: tuple[Token, ...] = args
|
|
839
|
+
|
|
840
|
+
def __repr__(self) -> str:
|
|
841
|
+
return StrNode(f"<GLOBAL - {', '.join((str(i) for i in self.env_variables))}")
|
|
842
|
+
|
|
843
|
+
def to_dict(self):
|
|
844
|
+
return {
|
|
845
|
+
"type": "GlobalNode",
|
|
846
|
+
"env_variables": self.env_variables
|
|
847
|
+
}
|
|
848
|
+
|
|
830
849
|
class CodeNode(ASTNode):
|
|
831
850
|
"""
|
|
832
851
|
Node representing a block of code to pass in arguments.
|
|
833
852
|
"""
|
|
834
|
-
def __init__(self, body: list[ASTNode], line: int):
|
|
853
|
+
def __init__(self, body: list[ASTNode], line: int, global_env_vars: Optional[GlobalNode] = None):
|
|
835
854
|
"""
|
|
836
855
|
:param body: list of Node representing the code already parsed
|
|
837
856
|
"""
|
|
838
857
|
super().__init__(line)
|
|
839
858
|
self.body = body
|
|
859
|
+
self.global_env_vars: Optional[GlobalNode] = global_env_vars
|
|
840
860
|
|
|
841
861
|
def __repr__(self):
|
|
842
862
|
return StrNode(f"<CODE> - {self.body}")
|
|
@@ -848,9 +868,11 @@ class CodeNode(ASTNode):
|
|
|
848
868
|
"""
|
|
849
869
|
return {
|
|
850
870
|
"type": "CodeNode",
|
|
871
|
+
"global_env_vars": self.global_env_vars.to_dict(),
|
|
851
872
|
"body": [token.to_dict() for token in self.body]
|
|
852
873
|
}
|
|
853
874
|
|
|
875
|
+
|
|
854
876
|
class EvalNode(ASTNode):
|
|
855
877
|
"""
|
|
856
878
|
Node representing an evaluation in the AST.
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellParser/dshell_parser.py
RENAMED
|
@@ -6,6 +6,7 @@ __all__ = [
|
|
|
6
6
|
"ast_to_dict",
|
|
7
7
|
]
|
|
8
8
|
|
|
9
|
+
from .ast_nodes import GlobalNode
|
|
9
10
|
from ..DshellTokenizer.dshell_token_type import Token
|
|
10
11
|
from ..DshellTokenizer.dshell_token_type import DshellTokenType as DTT
|
|
11
12
|
from ..DshellTokenizer.dshell_token_type import DTT_DATA
|
|
@@ -202,6 +203,18 @@ def parse(token_lines: list[list[Token]], start_node: ASTNode) -> tuple[list[AST
|
|
|
202
203
|
blocks.pop()
|
|
203
204
|
return blocks, pointer
|
|
204
205
|
|
|
206
|
+
elif first_token_line_value == 'global':
|
|
207
|
+
if not isinstance(last_block, CodeNode):
|
|
208
|
+
raise SyntaxError(f"[GLOBAL] No code open on line {first_token_line.position}")
|
|
209
|
+
|
|
210
|
+
for i in range(1, len_tokens_by_line):
|
|
211
|
+
ident = tokens_by_line[i]
|
|
212
|
+
if ident.type != DTT.IDENT:
|
|
213
|
+
raise ValueError(f"[GLOBAL] '{ident}' value must be a ident on line {first_token_line.position}")
|
|
214
|
+
|
|
215
|
+
global_node = GlobalNode(line, *tokens_by_line[1:])
|
|
216
|
+
last_block.global_env_vars = global_node
|
|
217
|
+
|
|
205
218
|
elif first_token_line_value == 'eval':
|
|
206
219
|
if len_tokens_by_line_since_command_name < 1:
|
|
207
220
|
raise SyntaxError(f"[EVAL] take one or more arguments on line {first_token_line.position}")
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellTokenizer/dshell_keywords.py
RENAMED
|
@@ -17,7 +17,7 @@ from ..DshellInterpreteur.dshell_iterators import IntIterator
|
|
|
17
17
|
dshell_keyword: set[str] = {
|
|
18
18
|
'if', 'else', 'elif', 'loop', '#end', 'var', '#loop', '#if', 'sleep',
|
|
19
19
|
'param', '#param', 'code', '#code', 'eval', 'return', 'break',
|
|
20
|
-
'catch', '#catch', 'raise'
|
|
20
|
+
'catch', '#catch', 'raise', 'global'
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
dshell_discord_keyword: set[str] = {
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name="dshellInterpreter",
|
|
8
|
-
version="1.2.
|
|
8
|
+
version="1.2.8.0",
|
|
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,159 +0,0 @@
|
|
|
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
|
-
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/__init__.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_channel.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_embed.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_file.py
RENAMED
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_member.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_message.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_pastbin.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/dshell_role.py
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DISCORD_COMMANDS/utils/utils_file.py
RENAMED
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellInterpreteur/errors.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellPreProcess/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/Dshell/DshellTokenizer/dshell_tokenizer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/dshellInterpreter.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/dshellInterpreter.egg-info/requires.txt
RENAMED
|
File without changes
|
{dshellinterpreter-1.2.7.10 → dshellinterpreter-1.2.8.0}/dshellInterpreter.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|