dekshell 0.2.42__py3-none-any.whl → 0.2.44__py3-none-any.whl

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.
@@ -37,7 +37,7 @@ from dektools.cmd.git import git_parse_modules, git_clean_dir, git_fetch_min, gi
37
37
  from ...utils.beep import sound_notify
38
38
  from ...utils.cmd import pack_context_full
39
39
  from ..markers.base.core import MarkerBase, get_inner_vars
40
- from ..markers.invoke import InvokeMarker, GotoMarker
40
+ from ..markers.invoke import InvokeMarker, GotoMarker, ImportMarker
41
41
  from ..redirect import search_bin_by_path_tree
42
42
 
43
43
 
@@ -100,44 +100,58 @@ def _remove_path(path):
100
100
  _remove_path(item)
101
101
 
102
102
 
103
- _eval_default = object()
103
+ _default_value = object()
104
104
 
105
105
 
106
- def _eval_mixin(expression, default=_eval_default, translate=False):
107
- context = get_inner_vars('__inner_context__', full=True)
106
+ def _parse_expression(expression, default=_default_value, translate=False):
107
+ context = get_inner_vars('__inner_context__')
108
+ try:
109
+ return MarkerBase.parse_expression(context, expression, translate)
110
+ except NameError:
111
+ if default is _default_value:
112
+ raise
113
+ else:
114
+ return default
115
+
116
+
117
+ def _eval_mixin(expression, default=_default_value, translate=False):
118
+ context = get_inner_vars('__inner_context__')
108
119
  try:
109
120
  return MarkerBase.eval_mixin(context, expression, translate)
110
121
  except NameError:
111
- if default is _eval_default:
122
+ if default is _default_value:
112
123
  raise
113
124
  else:
114
125
  return default
115
126
 
116
127
 
117
- def _eval_lines(expression, default=_eval_default):
118
- context = get_inner_vars('__inner_context__', full=True)
128
+ def _eval_lines(expression, default=_default_value):
129
+ context = get_inner_vars('__inner_context__')
119
130
  try:
120
131
  return MarkerBase.eval_lines(context, expression)
121
132
  except NameError:
122
- if default is _eval_default:
133
+ if default is _default_value:
123
134
  raise
124
135
  else:
125
136
  return default
126
137
 
127
138
 
128
- def _invoke(__placeholder__filepath, *args, **kwargs):
129
- marker_set = get_inner_vars('__inner_marker_set__', full=True)
130
- filepath = normal_path(__placeholder__filepath)
131
- cwd = os.getcwd()
132
- os.chdir(os.path.dirname(filepath))
133
- ret_value = marker_set.shell_exec(filepath, pack_context_full(args, kwargs))
134
- os.chdir(cwd)
135
- return ret_value
139
+ def _global_update(variables):
140
+ context = get_inner_vars('__inner_context__')
141
+ for k, v in variables.items():
142
+ MarkerBase.set_var_raw(context, k, v)
136
143
 
137
144
 
138
- def _goto(__placeholder__filepath, *args, **kwargs):
139
- marker_set = get_inner_vars('__inner_marker_set__', full=True)
140
- return marker_set.shell_exec(normal_path(__placeholder__filepath), pack_context_full(args, kwargs))
145
+ def _env_update(variables):
146
+ context = get_inner_vars('__inner_context__')
147
+ for k, v in variables.items():
148
+ context.add_env(k, v)
149
+
150
+
151
+ def _envs_update(variables):
152
+ context = get_inner_vars('__inner_context__')
153
+ for k, v in variables.items():
154
+ context.environ.add_item(k, v)
141
155
 
142
156
 
143
157
  def _defined(name):
@@ -207,7 +221,7 @@ def _time_mark(begin=True, name=None):
207
221
  if name is None:
208
222
  name = ''
209
223
  name = str(name).strip()
210
- marker_set = get_inner_vars('__inner_marker_set__', full=True)
224
+ marker_set = get_inner_vars('__inner_marker_set__')
211
225
  _now = time.time_ns()
212
226
  if begin:
213
227
  marker_set.vars.add_item(var_prefix + name, _now)
@@ -254,10 +268,27 @@ default_methods = {
254
268
  'timeout': shell_timeout,
255
269
  'retry': shell_retry,
256
270
  'run': shell_wrapper,
271
+ 'env': {
272
+ None: lambda k, v: _env_update({k: v}),
273
+ 'update': _env_update,
274
+ },
275
+ 'envs': {
276
+ None: lambda k, v: _envs_update({k: v}),
277
+ 'update': _envs_update,
278
+ },
279
+ 'expr': _parse_expression,
257
280
  'eval': _eval_mixin,
258
281
  'exec': _eval_lines,
259
- 'invoke': _invoke,
260
- 'goto': _goto,
282
+ 'var': {
283
+ None: lambda k, v: _global_update({k: v}),
284
+ 'update': _global_update,
285
+ },
286
+ 'invoke': lambda __placeholder__filepath, *args, **kwargs: InvokeMarker.execute_file(
287
+ None, __placeholder__filepath, args, kwargs),
288
+ 'goto': lambda __placeholder__filepath, *args, **kwargs: GotoMarker.execute_file(
289
+ None, __placeholder__filepath, args, kwargs),
290
+ 'imp': lambda __placeholder__filepath, *args, **kwargs: ImportMarker.execute_file(
291
+ None, __placeholder__filepath, args, kwargs),
261
292
  },
262
293
  'path': {
263
294
  **path_common_methods,
@@ -350,11 +381,6 @@ default_methods = {
350
381
 
351
382
  'beep': lambda x=True: sound_notify(x),
352
383
 
353
- 'invoke': lambda __placeholder__filepath, *args, **kwargs: InvokeMarker.execute_file(
354
- None, __placeholder__filepath, args, kwargs),
355
- 'goto': lambda __placeholder__filepath, *args, **kwargs: GotoMarker.execute_file(
356
- None, __placeholder__filepath, args, kwargs),
357
-
358
384
  'glob': {
359
385
  're': glob2re,
360
386
  'compile': glob_compile,
@@ -44,37 +44,36 @@ is_on_win = os.name == "nt"
44
44
  path_root = path_home[:path_home.find(os.sep)] if is_on_win else os.sep
45
45
 
46
46
 
47
- class _Env:
48
- def __getattr__(self, item):
49
- return os.environ.get(item.upper(), '')
50
-
51
- def __getitem__(self, item):
52
- return os.environ[item.upper()]
53
-
54
- def __contains__(self, item):
55
- return item.upper() in os.environ
47
+ class _EnvBase:
48
+ __getenv__ = None
56
49
 
57
-
58
- class _EnvS:
59
50
  def __getattr__(self, item):
60
- context = get_inner_vars('__inner_context__', full=True)
61
- return context.get_env(item.upper(), '')
51
+ context = get_inner_vars('__inner_context__')
52
+ return getattr(context, self.__getenv__)(item.upper(), '')
62
53
 
63
54
  def __getitem__(self, item):
64
- context = get_inner_vars('__inner_context__', full=True)
55
+ context = get_inner_vars('__inner_context__')
65
56
  default = object()
66
- ret = context.get_env(item.upper(), default)
57
+ ret = getattr(context, self.__getenv__)(item.upper(), default)
67
58
  if ret is default:
68
59
  raise KeyError(item)
69
60
  return ret
70
61
 
71
62
  def __contains__(self, item):
72
- context = get_inner_vars('__inner_context__', full=True)
63
+ context = get_inner_vars('__inner_context__')
73
64
  default = object()
74
- ret = context.get_env(item.upper(), default)
65
+ ret = getattr(context, self.__getenv__)(item.upper(), default)
75
66
  return ret is not default
76
67
 
77
68
 
69
+ class _Env(_EnvBase):
70
+ __getenv__ = 'get_env'
71
+
72
+
73
+ class _EnvS(_EnvBase):
74
+ __getenv__ = 'get_env_full'
75
+
76
+
78
77
  default_properties = {
79
78
  'meta': {
80
79
  'name': package_name,
@@ -46,8 +46,12 @@ def generate_markers(*args, **kwargs):
46
46
  TimeoutMarker, RetryMarker,
47
47
  IgnoreMarker,
48
48
  IgnoreErrorShellMarker, PrefixShellMarker,
49
- AssignCallMarker, AssignInvokerMarker, AssignGotoMarker, AssignTimeoutMarker, AssignRetryMarker,
50
- AssignExecMarker, AssignTranslatorEvalMarker, AssignEvalMarker, AssignCmdcallMarker, AssignCmdcallChainMarker,
49
+ AssignCallMarker, AssignInvokerMarker, AssignGotoMarker, AssignImportMarker, AssignTimeoutMarker,
50
+ AssignRetryMarker,
51
+ AssignExecMarker, AssignTranslatorEvalMarker, AssignEvalMarker,
52
+ AssignCommandRcSilenceMarker, AssignCommandRcMarker, AssignCommandOutputMarker,
53
+ AssignDecodeMarker, AssignEncodeMarker,
54
+ AssignEnvMarker, AssignEnvFullMarker, AssignCmdcallMarker, AssignCmdcallChainMarker,
51
55
  AssignMultiLineRawStrMarker, AssignMultiLineStrMarker, AssignRawStrMarker, AssignStrMarker,
52
56
  EmptyMarker, # must be at the tail
53
57
  ]
@@ -1,4 +1,3 @@
1
- import os
2
1
  import re
3
2
  import functools
4
3
  from dektools.str import deep_format, split_table_line, shlex_split, shlex_quote
@@ -99,8 +98,9 @@ class MarkerBase:
99
98
  def raise_(self, message):
100
99
  raise RaiseException(message)
101
100
 
102
- def set_var(self, context, array, index, value):
103
- self.set_var_raw(context, self.get_item(array, index, self.var_name_anonymous), value)
101
+ @classmethod
102
+ def set_var(cls, context, array, index, value):
103
+ cls.set_var_raw(context, cls.get_item(array, index, cls.var_name_anonymous), value)
104
104
 
105
105
  @staticmethod
106
106
  def set_var_raw(context, name, value):
@@ -114,7 +114,9 @@ class MarkerBase:
114
114
  def cmd_call_split(cls, s, max_item=None):
115
115
  if max_item == 0:
116
116
  return [], s.lstrip()
117
- m = re.match(rf'[ \t\f\r]*({cmd_call_prefix_simple}[{cmd_call_prefix_simple}]?)[ \t\f\r]*([^\W\d][\w.]*)', s)
117
+ m = re.match(
118
+ rf'''[ \t\f\r]*({cmd_call_prefix_simple}[{cmd_call_prefix_simple}]?)[ \t\f\r]*([^\W\d][\w.]*)'''
119
+ , s)
118
120
  if not m:
119
121
  return [], s.lstrip()
120
122
  rest = s[m.span()[1]:]
@@ -154,73 +156,83 @@ class MarkerBase:
154
156
  def handler(expression, _, __):
155
157
  expression = expression.lstrip()
156
158
  as_var = False
157
- ignore = False
159
+ ignore_errors = False
158
160
  while True:
159
161
  change = 0
160
162
  if not as_var and expression.startswith(cls.trans_marker__as_var):
161
163
  expression = expression[len(cls.trans_marker__as_var):].lstrip()
162
164
  as_var = True
163
- change +=1
164
- if not ignore and expression.startswith(cls.trans_marker__ignore):
165
+ change += 1
166
+ if not ignore_errors and expression.startswith(cls.trans_marker__ignore):
165
167
  expression = expression[len(cls.trans_marker__ignore):].lstrip()
166
- ignore = True
167
- change +=1
168
+ ignore_errors = True
169
+ change += 1
168
170
  if change in (0, 2):
169
171
  break
170
- value = handler_core(expression, ignore)
172
+ value = cls.parse_expression(context, expression, False, False, ignore_errors)
171
173
  if as_var:
172
174
  return context.add_variable_temp(value)
173
175
  return value
174
176
 
175
- def evaluate(expression, ignore, default):
177
+ return deep_format(
178
+ s,
179
+ # f"{re.escape(cls.trans_marker__begin)}({cls.trans_marker__set})?",
180
+ f"{re.escape(cls.trans_marker__begin)}",
181
+ re.escape(cls.trans_marker__end), handler, cls.trans_marker__escape)
182
+
183
+ @classmethod
184
+ def parse_expression(cls, context, expression, translate_eval=True, translate_others=True, ignore_errors=False):
185
+ def evaluate(expr, default):
176
186
  try:
177
- return cls.eval_mixin(context, expression, False)
187
+ return cls.eval_mixin(context, expr, translate_eval)
178
188
  except NameError:
179
- if ignore:
189
+ if ignore_errors:
180
190
  return default
181
191
  else:
182
192
  raise
183
193
 
184
- def handler_core(expression, ignore):
185
- if expression.startswith(cls.trans_marker_command_rc_silence):
186
- expression = expression[len(cls.trans_marker_command_rc_silence):]
187
- return shell_exitcode(expression, env=context.environ_full())
188
- elif expression.startswith(cls.trans_marker_command_rc):
189
- expression = expression[len(cls.trans_marker_command_rc):]
190
- return shell_wrapper(expression, check=False, env=context.environ_full())
191
- elif expression.startswith(cls.trans_marker_command_output):
192
- expression = expression[len(cls.trans_marker_command_output):]
193
- return shell_output(expression, env=context.environ_full())
194
- elif expression.startswith(cls.trans_marker_env):
195
- expression = expression[len(cls.trans_marker_env):]
196
- return os.getenv(expression.strip(), default_value)
197
- elif expression.startswith(cls.trans_marker_env_full):
198
- expression = expression[len(cls.trans_marker_env_full):]
199
- return context.get_env(expression.strip(), default_value)
200
- elif expression.startswith(cls.trans_marker_decode):
201
- expression = expression[len(cls.trans_marker_decode):]
202
- value = evaluate(expression, ignore, empty_value)
203
- if value is empty_value:
204
- return default_value
205
- return serializer.load(value)
206
- elif expression.startswith(cls.trans_marker_encode):
207
- expression = expression[len(cls.trans_marker_encode):]
208
- value = evaluate(expression, ignore, empty_value)
209
- if value is empty_value:
210
- return default_value
211
- return serializer.dump(value)
212
- else:
213
- return evaluate(expression, ignore, default_value)
214
-
215
194
  empty_value = object()
216
195
  default_value = ''
217
196
 
218
- translate = deep_format(
219
- s,
220
- # f"{re.escape(cls.trans_marker__begin)}({cls.trans_marker__set})?",
221
- f"{re.escape(cls.trans_marker__begin)}",
222
- re.escape(cls.trans_marker__end), handler, cls.trans_marker__escape)
223
- return translate
197
+ if expression.startswith(cls.trans_marker_command_rc_silence):
198
+ expression = expression[len(cls.trans_marker_command_rc_silence):]
199
+ if translate_others:
200
+ expression = cls.translate_case(context, expression, True)
201
+ return shell_exitcode(expression, env=context.environ_full())
202
+ elif expression.startswith(cls.trans_marker_command_rc):
203
+ expression = expression[len(cls.trans_marker_command_rc):]
204
+ if translate_others:
205
+ expression = cls.translate_case(context, expression, True)
206
+ return shell_wrapper(expression, check=False, env=context.environ_full())
207
+ elif expression.startswith(cls.trans_marker_command_output):
208
+ expression = expression[len(cls.trans_marker_command_output):]
209
+ if translate_others:
210
+ expression = cls.translate_case(context, expression, True)
211
+ return shell_output(expression, env=context.environ_full())
212
+ elif expression.startswith(cls.trans_marker_env):
213
+ expression = expression[len(cls.trans_marker_env):]
214
+ if translate_others:
215
+ expression = cls.translate_case(context, expression, True)
216
+ return context.get_env(expression.strip(), default_value)
217
+ elif expression.startswith(cls.trans_marker_env_full):
218
+ expression = expression[len(cls.trans_marker_env_full):]
219
+ if translate_others:
220
+ expression = cls.translate_case(context, expression, True)
221
+ return context.get_env_full(expression.strip(), default_value)
222
+ elif expression.startswith(cls.trans_marker_decode):
223
+ expression = expression[len(cls.trans_marker_decode):]
224
+ value = evaluate(expression, empty_value)
225
+ if value is empty_value:
226
+ return default_value
227
+ return serializer.load(value)
228
+ elif expression.startswith(cls.trans_marker_encode):
229
+ expression = expression[len(cls.trans_marker_encode):]
230
+ value = evaluate(expression, empty_value)
231
+ if value is empty_value:
232
+ return default_value
233
+ return serializer.dump(value)
234
+ else:
235
+ return evaluate(expression, default_value)
224
236
 
225
237
  @classproperty
226
238
  @functools.lru_cache(None)
@@ -7,7 +7,7 @@ from dektools.typing import NoneType
7
7
  from . import MarkerBase, TransformerMarker, ExitException, QuitContextException
8
8
 
9
9
 
10
- def get_inner_vars(*var_name_list, full=False):
10
+ def get_inner_vars(*var_name_list, full=True):
11
11
  def walk(attr):
12
12
  depth = 1
13
13
  while True:
@@ -87,13 +87,25 @@ class MarkerContext:
87
87
  environ.update(self.environ.flat())
88
88
  return environ
89
89
 
90
- def get_env(self, name, default=None):
90
+ def get_env_full(self, name, default=None):
91
91
  empty = object()
92
92
  value = self.environ.get_item(name, empty)
93
93
  if value is not empty:
94
94
  return value
95
+ return self.get_env(name, default)
96
+
97
+ @staticmethod
98
+ def get_env(name, default=None):
95
99
  return os.environ.get(name, default)
96
100
 
101
+ @staticmethod
102
+ def add_env(key, value):
103
+ os.environ[key] = value
104
+
105
+ @staticmethod
106
+ def remove_env(key):
107
+ os.environ.pop(key, None)
108
+
97
109
 
98
110
  class HiddenVarSet:
99
111
  def __init__(self):
@@ -192,11 +204,12 @@ class MarkerNode:
192
204
  @classmethod
193
205
  def execute_nodes(cls, context, marker_set, nodes):
194
206
  __inner_marker_set__ = marker_set # noqa
207
+ context_final = None
195
208
  while nodes:
196
209
  node = nodes.pop(0)
197
210
  result = node.bubble_continue(context, marker_set, node)
198
211
  if result is not None:
199
- return result
212
+ return result, context
200
213
  else:
201
214
  try:
202
215
  changes = node.marker.execute(
@@ -205,7 +218,7 @@ class MarkerNode:
205
218
  node, marker_set
206
219
  )
207
220
  except QuitContextException as e:
208
- return QuitContext(context, e.args[0])
221
+ return QuitContext(context, e.args[0]), context
209
222
  except ExitException:
210
223
  raise
211
224
  except Exception as e:
@@ -239,9 +252,10 @@ class MarkerNode:
239
252
  context_ = context.derive().update_variables(variables)
240
253
  elif changes is not None:
241
254
  raise TypeError(f"Unknown type of changes: {changes}")
255
+ context_final = context_
242
256
  if nodes_ is None:
243
257
  nodes_ = node.children[:]
244
- result = cls.execute_nodes(
258
+ result, _ = cls.execute_nodes(
245
259
  context_,
246
260
  marker_set,
247
261
  nodes_
@@ -251,16 +265,20 @@ class MarkerNode:
251
265
  if node is node_cursor: # Depth of the location
252
266
  nodes[:0] = node_loop_list
253
267
  else:
254
- return result
268
+ return result, context_
255
269
  elif isinstance(result, QuitContext):
256
270
  if result.context is context:
257
- return result
271
+ return result, context_
258
272
  else:
259
273
  if callback:
260
274
  callback(result)
275
+ if context_final is None:
276
+ context_final = context
277
+ return None, context_final
261
278
 
262
279
  def execute(self, context, marker_set):
263
- return QuitContext.real(self.execute_nodes(context, marker_set, [self]))
280
+ result, context = self.execute_nodes(context, marker_set, [self])
281
+ return QuitContext.real(result), context
264
282
 
265
283
  def walk(self, cb, depth=0):
266
284
  cb(self, depth)
@@ -281,11 +299,20 @@ class MarkerNode:
281
299
  return self.index + 1
282
300
 
283
301
 
302
+ class ShellResult:
303
+ def __init__(self, marker_set: 'MarkerSet', root: MarkerNode, context: MarkerContext, result):
304
+ self.marker_set = marker_set
305
+ self.root = root
306
+ self.context = context
307
+ self.result = result
308
+
309
+
284
310
  class MarkerSet:
285
311
  node_cls = MarkerNode
286
312
  context_cls = MarkerContext
287
313
  transformer_cls = TransformerMarker
288
314
  hidden_var_set_cls = HiddenVarSet
315
+ shell_result_cls = ShellResult
289
316
 
290
317
  def __init__(self, markers_cls, shell_exec, shell_cmd):
291
318
  markers = []
@@ -353,7 +380,8 @@ class MarkerSet:
353
380
  def execute(self, commands, context, ln=None):
354
381
  try:
355
382
  root = self.generate_tree(commands, ln)
356
- return root.execute(
383
+ result, context = root.execute(
357
384
  self.context_cls().update_variables({**(context or {}), **dict(__inner_marker_set__=self)}), self)
385
+ return self.shell_result_cls(self, root, context, result)
358
386
  except ExitException:
359
387
  pass
@@ -12,5 +12,5 @@ class DefineMarker(MarkerNoTranslator):
12
12
  except NameError:
13
13
  expression = self.get_item(args, 2)
14
14
  if expression:
15
- result = self.eval_mixin(context, expression)
15
+ result = self.parse_expression(context, expression)
16
16
  self.set_var_raw(context, var_name, result)
@@ -24,9 +24,9 @@ class EnvMarker(MarkerEnvBase):
24
24
  if key:
25
25
  key = key.upper()
26
26
  if value is None:
27
- os.environ.pop(key, None)
27
+ context.remove_env(key)
28
28
  else:
29
- os.environ[key] = value
29
+ context.add_env(key, value)
30
30
 
31
31
 
32
32
  class EnvShellMarker(MarkerEnvBase):
@@ -22,7 +22,7 @@ class ExecTranslatorMarker(MarkerBase):
22
22
 
23
23
 
24
24
  class ExecLinesMarker(MarkerWithEnd, MarkerNoTranslator):
25
- tag_head = '=='
25
+ tag_head = cmd_call_eval_prefix * 2
26
26
 
27
27
  def execute(self, context, command, marker_node, marker_set):
28
28
  code = self.get_inner_content(context, marker_node, translate=False)
@@ -31,7 +31,7 @@ class ExecLinesMarker(MarkerWithEnd, MarkerNoTranslator):
31
31
 
32
32
 
33
33
  class ExecLinesUpdateMarker(MarkerWithEnd, MarkerNoTranslator):
34
- tag_head = '==='
34
+ tag_head = cmd_call_eval_prefix * 3
35
35
 
36
36
  def execute(self, context, command, marker_node, marker_set):
37
37
  code = self.get_inner_content(context, marker_node, translate=False)
@@ -49,4 +49,4 @@ class ForMarker(MarkerWithEnd, MarkerNoTranslator):
49
49
  ]
50
50
 
51
51
  def get_expression_value(self, context, expression):
52
- return self.eval_mixin(context, expression)
52
+ return self.parse_expression(context, expression)
@@ -35,9 +35,9 @@ class Function:
35
35
  self.body = body
36
36
 
37
37
  def __call__(self, *args, **kwargs):
38
- context, marker_set = get_inner_vars('__inner_context__', '__inner_marker_set__', full=True)
38
+ context, marker_set = get_inner_vars('__inner_context__', '__inner_marker_set__')
39
39
  context = context.derive().update_variables(self.pack_variables(context, args, kwargs))
40
- return QuitContext.real(marker_set.node_cls.execute_nodes(context, marker_set, self.body[:]))
40
+ return QuitContext.real(marker_set.node_cls.execute_nodes(context, marker_set, self.body[:])[0])
41
41
 
42
42
  def __str__(self):
43
43
  return f"{self.__class__.__name__}<{self.name}>"
@@ -48,10 +48,11 @@ class Function:
48
48
 
49
49
  class FunctionMarker(MarkerWithEnd):
50
50
  tag_head = "function"
51
+ function_cls = Function
51
52
 
52
53
  def execute(self, context, command, marker_node, marker_set):
53
54
  name, params = assign_list([''] * 2, self.split_raw(command, 2)[1:])
54
- self.set_var_raw(context, name, Function(name, params, marker_node.children[:]))
55
+ self.set_var_raw(context, name, self.function_cls(name, params, marker_node.children[:]))
55
56
  return []
56
57
 
57
58
 
@@ -60,7 +61,7 @@ class ReturnMarker(MarkerNoTranslator):
60
61
 
61
62
  def execute(self, context, command, marker_node, marker_set):
62
63
  args = self.split_raw(command, 1, self.tag_head)
63
- self.ret(self.eval_mixin(context, args[1]))
64
+ self.ret(self.parse_expression(context, args[1]))
64
65
 
65
66
 
66
67
  class RaiseMarker(MarkerBase):
@@ -18,7 +18,7 @@ class MarkerWithJudge(MarkerWithEnd, MarkerNoTranslator):
18
18
  def get_condition_result(self, context, expression):
19
19
  if not expression:
20
20
  return self.empty_expected_value
21
- return self.eval_mixin(context, expression)
21
+ return self.parse_expression(context, expression)
22
22
 
23
23
 
24
24
  class IfElseMarker(MarkerWithJudge):
@@ -9,7 +9,7 @@ class InputMarker(MarkerWithEnd, MarkerNoTranslator):
9
9
  def execute(self, context, command, marker_node, marker_set):
10
10
  command_text = self.get_inner_content(context, marker_node, sep='', translate=True).strip()
11
11
  expression = self.split_raw(command, 1, self.tag_head)[1]
12
- inputs = self.eval_mixin(context, expression)
12
+ inputs = self.parse_expression(context, expression)
13
13
  rc = shell_with_input(command_text, inputs, env=context.environ_full())
14
14
  if rc:
15
15
  raise subprocess.CalledProcessError(rc, command_text)
@@ -17,7 +17,7 @@ class MarkerInvokerBase(MarkerBase):
17
17
  @classmethod
18
18
  def execute_file(cls, marker_set, filepath, args, kwargs):
19
19
  if marker_set is None:
20
- marker_set = get_inner_vars('__inner_marker_set__', full=True)
20
+ marker_set = get_inner_vars('__inner_marker_set__')
21
21
  return cls._run_file(marker_set, normal_path(filepath), pack_context_full(args, kwargs))
22
22
 
23
23
  @classmethod
@@ -30,7 +30,7 @@ class GotoMarker(MarkerInvokerBase):
30
30
 
31
31
  @classmethod
32
32
  def _run_file(cls, marker_set, filepath, attrs):
33
- return marker_set.shell_exec(filepath, attrs)
33
+ return marker_set.shell_exec(filepath, attrs).result
34
34
 
35
35
 
36
36
  class InvokeMarker(MarkerInvokerBase):
@@ -40,6 +40,26 @@ class InvokeMarker(MarkerInvokerBase):
40
40
  def _run_file(cls, marker_set, filepath, attrs):
41
41
  cwd = os.getcwd()
42
42
  os.chdir(os.path.dirname(filepath))
43
- ret_value = marker_set.shell_exec(filepath, attrs)
43
+ ret_value = marker_set.shell_exec(filepath, attrs).result
44
44
  os.chdir(cwd)
45
45
  return ret_value
46
+
47
+
48
+ class Closure:
49
+ def __init__(self, shell_result):
50
+ self.__variables__ = shell_result.context.variables
51
+
52
+ def __getattr__(self, item):
53
+ return self.__variables__.get_item(item)
54
+
55
+ def __getitem__(self, item):
56
+ return self.__variables__.get_item(item, None)
57
+
58
+
59
+ class ImportMarker(MarkerInvokerBase):
60
+ tag_head = "import"
61
+ closure_cls = Closure
62
+
63
+ @classmethod
64
+ def _run_file(cls, marker_set, filepath, attrs):
65
+ return cls.closure_cls(marker_set.shell_exec(filepath, attrs))
@@ -1,8 +1,9 @@
1
1
  import re
2
- from .base import MarkerBase, MarkerWithEnd, MarkerNoTranslator, cmd_call_prefix_simple, cmd_call_prefix_chain
2
+ from .base import MarkerBase, MarkerWithEnd, MarkerNoTranslator, cmd_call_prefix_simple, cmd_call_prefix_chain, \
3
+ cmd_call_eval_prefix, cmd_call_eval_trans_prefix
3
4
  from .function import CallMarker
4
5
  from .shell import TimeoutMarker, RetryMarker
5
- from .invoke import MarkerInvokerBase, InvokeMarker, GotoMarker
6
+ from .invoke import MarkerInvokerBase, InvokeMarker, GotoMarker, ImportMarker
6
7
 
7
8
 
8
9
  class MarkerAssignBase(MarkerBase):
@@ -57,21 +58,21 @@ class AssignMultiLineRawStrMarker(AssignMultiLineStrMarker, MarkerNoTranslator):
57
58
 
58
59
 
59
60
  class AssignEvalMarker(MarkerAssignValueBase, MarkerNoTranslator):
60
- tag_head_re_args = '='
61
+ tag_head_re_args = cmd_call_eval_prefix
61
62
 
62
63
  def get_value(self, context, marker_node, marker_set, expression):
63
64
  return self.eval(context, expression)
64
65
 
65
66
 
66
67
  class AssignTranslatorEvalMarker(MarkerAssignValueBase):
67
- tag_head_re_args = '=:'
68
+ tag_head_re_args = cmd_call_eval_trans_prefix
68
69
 
69
70
  def get_value(self, context, marker_node, marker_set, expression):
70
71
  return self.eval(context, expression)
71
72
 
72
73
 
73
74
  class AssignExecMarker(MarkerAssignBase, MarkerWithEnd, MarkerNoTranslator):
74
- tag_head_re_args = '=='
75
+ tag_head_re_args = cmd_call_eval_prefix * 2
75
76
 
76
77
  def execute(self, context, command, marker_node, marker_set):
77
78
  code = self.get_inner_content(context, marker_node, translate=False)
@@ -81,15 +82,55 @@ class AssignExecMarker(MarkerAssignBase, MarkerWithEnd, MarkerNoTranslator):
81
82
  return []
82
83
 
83
84
 
84
- class AssignCmdcallMarker(MarkerAssignValueBase):
85
- tag_head_re_args_raw = cmd_call_prefix_simple
86
- tag_head_re_args = re.escape(tag_head_re_args_raw)
85
+ class MarkerAssignValueParseExprBase(MarkerAssignValueBase):
86
+ tag_head_re_args_raw = None
87
87
 
88
88
  def get_value(self, context, marker_node, marker_set, expression):
89
- return self.eval_mixin(context, self.tag_head_re_args_raw + expression, False)
89
+ return self.parse_expression(context, self.tag_head_re_args_raw + expression, False)
90
+
91
+
92
+ class AssignCommandRcSilenceMarker(MarkerAssignValueParseExprBase):
93
+ tag_head_re_args_raw = MarkerBase.trans_marker_command_rc_silence
94
+ tag_head_re_args = re.escape(MarkerBase.trans_marker_command_rc_silence)
95
+
96
+
97
+ class AssignCommandRcMarker(MarkerAssignValueParseExprBase):
98
+ tag_head_re_args_raw = MarkerBase.trans_marker_command_rc
99
+ tag_head_re_args = re.escape(MarkerBase.trans_marker_command_rc)
100
+
101
+
102
+ class AssignCommandOutputMarker(MarkerAssignValueParseExprBase):
103
+ tag_head_re_args_raw = MarkerBase.trans_marker_command_output
104
+ tag_head_re_args = re.escape(MarkerBase.trans_marker_command_output)
105
+
106
+
107
+
108
+ class AssignDecodeMarker(MarkerAssignValueParseExprBase):
109
+ tag_head_re_args_raw = MarkerBase.trans_marker_decode
110
+ tag_head_re_args = re.escape(MarkerBase.trans_marker_decode)
111
+
90
112
 
113
+ class AssignEncodeMarker(MarkerAssignValueParseExprBase):
114
+ tag_head_re_args_raw = MarkerBase.trans_marker_encode
115
+ tag_head_re_args = re.escape(MarkerBase.trans_marker_encode)
91
116
 
92
- class AssignCmdcallChainMarker(AssignCmdcallMarker):
117
+
118
+ class AssignEnvMarker(MarkerAssignValueParseExprBase):
119
+ tag_head_re_args_raw = MarkerBase.trans_marker_env
120
+ tag_head_re_args = re.escape(MarkerBase.trans_marker_env)
121
+
122
+
123
+ class AssignEnvFullMarker(MarkerAssignValueParseExprBase):
124
+ tag_head_re_args_raw = MarkerBase.trans_marker_env_full
125
+ tag_head_re_args = re.escape(MarkerBase.trans_marker_env_full)
126
+
127
+
128
+ class AssignCmdcallMarker(MarkerAssignValueParseExprBase):
129
+ tag_head_re_args_raw = cmd_call_prefix_simple
130
+ tag_head_re_args = re.escape(tag_head_re_args_raw)
131
+
132
+
133
+ class AssignCmdcallChainMarker(MarkerAssignValueParseExprBase):
93
134
  tag_head_re_args_raw = cmd_call_prefix_chain + cmd_call_prefix_simple
94
135
  tag_head_re_args = re.escape(tag_head_re_args_raw)
95
136
 
@@ -120,6 +161,10 @@ class AssignGotoMarker(AssignMarkerInvokerBase, GotoMarker):
120
161
  tag_head_re_args = r'goto[ \t\f\r\n]+'
121
162
 
122
163
 
164
+ class AssignImportMarker(AssignMarkerInvokerBase, ImportMarker):
165
+ tag_head_re_args = r'import[ \t\f\r\n]+'
166
+
167
+
123
168
  class AssignTimeoutMarker(MarkerAssignValueBase, TimeoutMarker):
124
169
  tag_head = None
125
170
  tag_head_re_args = r'timeout[ \t\f\r\n]+'
@@ -29,4 +29,4 @@ class WhileMarker(MarkerWithEnd, MarkerNoTranslator):
29
29
  expression = command.split(self.tag_head, 1)[-1].strip()
30
30
  if not expression:
31
31
  return True
32
- return self.eval_mixin(context, expression)
32
+ return self.parse_expression(context, expression)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dekshell
3
- Version: 0.2.42
3
+ Version: 0.2.44
4
4
  Author-Email: sanzenwin <sanzenwin@gmail.com>
5
5
  License: MIT
6
6
  Requires-Python: >=3.8
@@ -1,34 +1,34 @@
1
- dekshell-0.2.42.dist-info/METADATA,sha256=_Qmh2L_sLWIq08ko5SNnZZITaHfsXTMxgNUUQ4zKXCE,573
2
- dekshell-0.2.42.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
- dekshell-0.2.42.dist-info/entry_points.txt,sha256=d-kbfULiUTZWIBBsrQF3J_-wESncF-4K2rwHT08grlI,75
1
+ dekshell-0.2.44.dist-info/METADATA,sha256=6Xsby8G1U04hzm55dWk8guaay6q8AGdoHvIcXiFKte0,573
2
+ dekshell-0.2.44.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
+ dekshell-0.2.44.dist-info/entry_points.txt,sha256=d-kbfULiUTZWIBBsrQF3J_-wESncF-4K2rwHT08grlI,75
4
4
  dekshell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  dekshell/click/__entry__.py,sha256=CMuxUzXoEe4TcHFZwv-MNFwHnu1HSZCDpXFpqQ814uM,42
6
6
  dekshell/click/__init__.py,sha256=r-AHdO9CEEVvTN20-8Jozr6Zh8XSv_BnktYRwrlhtrE,2046
7
7
  dekshell/core/__init__.py,sha256=isDEKwk1odLdvTQNCILCtVNBuXp1uFVPz_uTDNihkVU,5547
8
8
  dekshell/core/contexts/__init__.py,sha256=ynsfv37azOKfI2UKd0iPl2M6iBW-k5cb1BqSLOWuJpI,482
9
- dekshell/core/contexts/methods.py,sha256=uSepT9G6VT2NSs_EtSWZdFD3kt6dwcHcZOSknPougCg,11089
10
- dekshell/core/contexts/properties.py,sha256=yilnRe2I6FTIui4kXUBCWvH2ymvpEfc_13on8pAZwnY,3456
11
- dekshell/core/markers/__init__.py,sha256=yRQazZ1dxMltFao_RQnDnawSnQcjN_4B930MjJhaZ40,1968
12
- dekshell/core/markers/base/__init__.py,sha256=CsbNYGQ2Od3XdekR9RFMJ7mo9Roj-LlXS62SY50fiAY,16826
13
- dekshell/core/markers/base/core.py,sha256=InsUA3md2gC6GyXQsvARfeNTrfbVD3gGOYxTM8VqqPA,11679
9
+ dekshell/core/contexts/methods.py,sha256=3Bzfv_t8At5MqR0xD7qT8zye6KQySeXr0HpwuendrdE,11789
10
+ dekshell/core/contexts/properties.py,sha256=TQonN3T_K2cB2uakq_DVVB13B-IFwoM6t2ZkL_OMekw,3365
11
+ dekshell/core/markers/__init__.py,sha256=ov-mU1Bt-JbifBqJAWIywduWvyGI4WkJUx5LGZNVxhg,2178
12
+ dekshell/core/markers/base/__init__.py,sha256=WGxAr7GRDJI4-HRaLFBasTei-aPyApAnlpfbOaKmmvw,17385
13
+ dekshell/core/markers/base/core.py,sha256=6GPz8YVWgOPjGXtS04oa85P5LUDSg4H16rvVgiPz_EA,12556
14
14
  dekshell/core/markers/base/shell.py,sha256=fiFsTUDI8pSDDUCk834OI4ajri2qNWFJkLVhmUk2uAs,484
15
15
  dekshell/core/markers/commands.py,sha256=mDRj4dSfKbDaZ_ts4lPXd6wftvGFI4VKkRoIzxV7otA,1696
16
16
  dekshell/core/markers/comment.py,sha256=U1U3Xc4-giTqSEAPa4E_DmilZM9hs9zG-PCJ9nn4y5U,965
17
- dekshell/core/markers/define.py,sha256=LpMSfz9ziXq2aFJ6oMpUFFo93TpBx7GxKYNzCeht4fQ,516
17
+ dekshell/core/markers/define.py,sha256=Xlw_YPOWlmbopVIHhIeAKWSZhHhXmqb3gCbXxvuH4BQ,522
18
18
  dekshell/core/markers/echo.py,sha256=1H61qQbY9tZnrKsdTI_shTmDY5ZaSGipDuBSRptAuZw,660
19
19
  dekshell/core/markers/empty.py,sha256=pWKsHlrp6uXWU6blqOs0IgN_3kYm1OmDQiKGPERabAo,79
20
- dekshell/core/markers/env.py,sha256=6ZtiMNdKFbGR_DBjG6C7A8L_lJsiymN5Y5AbnTzyMrE,1158
21
- dekshell/core/markers/exec.py,sha256=4_7FRUEgbAtt0_9r8TmOar_Zi6VXxe6E7p3RL6sVgQg,2705
22
- dekshell/core/markers/for_.py,sha256=uNOEwyDsjffttEBtUYasdlj7FP_sGnQzWuTV5d5esHY,2142
23
- dekshell/core/markers/function.py,sha256=rLi8Lc9nf7ex3xdj8-VdJkgC1qXpr5JVMndH1YlH4mM,3815
24
- dekshell/core/markers/if_.py,sha256=bBG1fDCZd5alE5FSm0QhgHl6ZJn5awiqZAXnPnO-thc,1112
25
- dekshell/core/markers/input.py,sha256=O0yvGtt1uhbpE2gOReLseAmshVpZYMW3zV-OabZt0lw,1182
26
- dekshell/core/markers/invoke.py,sha256=ReE-i-ji2Bl90M8xLi8-kZrc-lL5mRUmjbGPoRcIoPw,1452
20
+ dekshell/core/markers/env.py,sha256=hU6irauFrvsUgK9j6jifosiMn0b6mt3aOf5t9oKhxS4,1160
21
+ dekshell/core/markers/exec.py,sha256=3yWpaCpASrMwzqVslDNzBaUVL7Lbn-zWMs-dOxUePZU,2744
22
+ dekshell/core/markers/for_.py,sha256=wQnK3-o0dQl4A2wx8xgs6V2dzgEjEbnt4MML2fh2x8U,2148
23
+ dekshell/core/markers/function.py,sha256=j8Cz4ouBQi_0dT6Q6pfJie-1rfIZuSIcWzGBlsKCSd8,3850
24
+ dekshell/core/markers/if_.py,sha256=UqEnR0X9bKO7hEKol3MJNWXvP7fuJAGt8zwk3xlBCuk,1118
25
+ dekshell/core/markers/input.py,sha256=94SWaeLnwtxRdIn9Ck0IxMZL6vOXVCedUmsp5IPAwWo,1188
26
+ dekshell/core/markers/invoke.py,sha256=ESL2DE9DTaq33AnrXpvEudp1qtoeZFKOhLL12OQpcs0,1975
27
27
  dekshell/core/markers/pip_.py,sha256=mxXa_oqcrk4Qz-HvhlkMoirsl-SbM9Fz610leNqP1o0,832
28
28
  dekshell/core/markers/redirect.py,sha256=cpTQaXFAuSwprsrhUNP0xTGDmu06HGNQVcwKsETEjas,1981
29
29
  dekshell/core/markers/shell.py,sha256=43BDAAzMdmgZmemkW5buh_w4LL1GDGw-s9fNZo6vhag,1929
30
- dekshell/core/markers/var.py,sha256=CnmBDQvA5XcQlioczXFhCvIbDc8ex4RIAgDeQvFdIiY,5176
31
- dekshell/core/markers/while_.py,sha256=e7lI5jsIM-qxNHMY_wUyCMvvesdXQibR5Ez2jNO9csc,1195
30
+ dekshell/core/markers/var.py,sha256=ZNhyH6wHz3H6fM7L28dfaI-7_cqJY8m6kGE5hP756i8,6884
31
+ dekshell/core/markers/while_.py,sha256=Q0SaElyXSrxg-wS_rfCcxMsmw9jf-0SgN1ICn860T4A,1201
32
32
  dekshell/core/plugin/__init__.py,sha256=jAB_KnnHJsyJR_zIfBU_HNLngyhcyyqVv05PdlNZtF8,428
33
33
  dekshell/core/redirect.py,sha256=6YCJpG0TkQ4WMt7LBtDD_W1T-C-QkLtGRQw0S60qe54,1058
34
34
  dekshell/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -37,4 +37,4 @@ dekshell/utils/cmd.py,sha256=K9FbXgHcGFchHA58xI0_t4YK4yb8XkWbxsNoztYRx3Y,518
37
37
  dekshell/utils/pkg.py,sha256=TgYqRqawoJfjkxt6UAHnp9ttmpjuHiWRFbqxADOS1VE,1337
38
38
  dekshell/utils/serializer.py,sha256=aIdF2Wzo-qHmIshv46jn1XD0X66vQ1JFdU-g3ZFbH2w,386
39
39
  dekshell/utils/shell.py,sha256=0NoA2-SOOMinbmZZipwzL-npBbzPOdWEfdPVYqq5G5g,92
40
- dekshell-0.2.42.dist-info/RECORD,,
40
+ dekshell-0.2.44.dist-info/RECORD,,