dekshell 0.1.99__tar.gz → 0.2.6__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.
Files changed (39) hide show
  1. {dekshell-0.1.99 → dekshell-0.2.6}/PKG-INFO +3 -2
  2. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/__init__.py +7 -3
  3. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/contexts/methods.py +61 -5
  4. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/contexts/properties.py +17 -0
  5. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/__init__.py +5 -5
  6. dekshell-0.1.99/dekshell/core/markers/shell.py → dekshell-0.2.6/dekshell/core/markers/commands.py +1 -1
  7. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/invoke.py +2 -2
  8. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/redirect.py +1 -1
  9. dekshell-0.2.6/dekshell/core/markers/shell.py +56 -0
  10. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/var.py +10 -1
  11. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/utils/cmd.py +1 -1
  12. {dekshell-0.1.99 → dekshell-0.2.6}/pyproject.toml +3 -2
  13. dekshell-0.1.99/dekshell/core/markers/timout.py +0 -26
  14. {dekshell-0.1.99 → dekshell-0.2.6}/README.md +0 -0
  15. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/__init__.py +0 -0
  16. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/click/__entry__.py +0 -0
  17. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/click/__init__.py +0 -0
  18. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/contexts/__init__.py +0 -0
  19. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/base/__init__.py +0 -0
  20. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/base/core.py +0 -0
  21. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/comment.py +0 -0
  22. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/define.py +0 -0
  23. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/echo.py +0 -0
  24. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/empty.py +0 -0
  25. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/env.py +0 -0
  26. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/exec.py +0 -0
  27. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/for_.py +0 -0
  28. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/function.py +0 -0
  29. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/if_.py +0 -0
  30. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/input.py +0 -0
  31. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/pip_.py +0 -0
  32. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/markers/while_.py +0 -0
  33. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/plugin/__init__.py +0 -0
  34. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/core/redirect.py +0 -0
  35. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/utils/__init__.py +0 -0
  36. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/utils/beep.py +0 -0
  37. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/utils/pkg.py +0 -0
  38. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/utils/serializer.py +0 -0
  39. {dekshell-0.1.99 → dekshell-0.2.6}/dekshell/utils/shell.py +0 -0
@@ -1,11 +1,12 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dekshell
3
- Version: 0.1.99
3
+ Version: 0.2.6
4
4
  Author-Email: sanzenwin <sanzenwin@gmail.com>
5
5
  License: MIT
6
6
  Requires-Python: >=3.8
7
7
  Requires-Dist: packaging<=23.1
8
- Requires-Dist: dektools[date,fetch]<1.0.0
8
+ Requires-Dist: extra-platforms<=3.1.0
9
+ Requires-Dist: dektools[date,fetch,ignore,ps,tab]<1.0.0
9
10
  Requires-Dist: dekmedia[audio]<1.0.0
10
11
  Description-Content-Type: text/markdown
11
12
 
@@ -17,8 +17,12 @@ from ..utils.shell import shell_bin
17
17
  from ..utils.cmd import ak2cmd, pack_context_full
18
18
 
19
19
 
20
- def shell_file(__not_use_this_var_name__, *args, **kwargs):
21
- shell_wrapper(f'{shell_bin} rf {__not_use_this_var_name__} {ak2cmd(args, kwargs)}')
20
+ def shell_file(__placeholder__filepath, *args, **kwargs):
21
+ shell_wrapper(f'{shell_bin} rf "{__placeholder__filepath}" {ak2cmd(args, kwargs)}')
22
+
23
+
24
+ def shell_file_cd(__placeholder__filepath, *args, **kwargs):
25
+ shell_wrapper(f'{shell_bin} rfc "{__placeholder__filepath}" {ak2cmd(args, kwargs)}')
22
26
 
23
27
 
24
28
  def shell_command_file_cd(filepath, **kwargs):
@@ -83,7 +87,7 @@ def shell_command_batch_core(
83
87
  def shell_exec(filepath, c=None):
84
88
  return shell_command_file(
85
89
  filepath,
86
- context=(context or {}) | (c or {}),
90
+ context=c or {},
87
91
  marker=marker,
88
92
  ms_names=ms_names,
89
93
  marker_set_cls=marker_set_cls,
@@ -1,10 +1,13 @@
1
1
  import os
2
+ import shutil
2
3
  import sys
3
4
  import tempfile
4
5
  import getpass
6
+ from functools import reduce
7
+ from itertools import chain
5
8
  from pathlib import Path
6
9
  from dektools.file import sure_dir, write_file, read_text, remove_path, sure_parent_dir, normal_path, \
7
- format_path_desc, read_file, split_ext, path_ext, clear_dir, \
10
+ format_path_desc, read_file, split_ext, path_ext, clear_dir, copy_recurse_ignore, \
8
11
  split_file, combine_split_files, remove_split_files, meta_split_file, tree, iglob, \
9
12
  where, where_list, which, which_list
10
13
  from dektools.hash import hash_file
@@ -14,8 +17,12 @@ from dektools.net import get_available_port
14
17
  from dektools.func import FuncAnyArgs
15
18
  from dektools.fetch import download_file
16
19
  from dektools.download import download_from_http
20
+ from dektools.ps.process import process_detail, process_kill, process_list_all
17
21
  from dektools.time import now
18
22
  from dektools.str import shlex_split, shlex_quote
23
+ from dektools.shell import shell_wrapper, is_user_admin
24
+ from dektools.match import GeneralMatcher, glob2re, glob_compile, glob_match
25
+ from dektools.cmd.git import git_clean_dir, git_apply, git_parse_modules, git_fetch_min, git_list_remotes, git_head
19
26
  from ...utils.beep import sound_notify
20
27
  from ..markers.base.core import MarkerBase, get_inner_vars
21
28
  from ..markers.invoke import InvokeMarker, GotoMarker
@@ -102,6 +109,26 @@ def _xeval(expression, default=_xeval_default, translate=False):
102
109
  return default
103
110
 
104
111
 
112
+ def _install(name):
113
+ def posix(exe):
114
+ s = f"{exe} install -y {name}"
115
+ if is_user_admin():
116
+ s = 'sudo ' + command
117
+ return s
118
+
119
+ if shutil.which('apt-get'):
120
+ command = posix('apt-get')
121
+ elif shutil.which('yum'):
122
+ command = posix('yum')
123
+ elif shutil.which('brew'):
124
+ command = f"brew install {name}"
125
+ elif shutil.which('choco'):
126
+ command = f"choco install -y {name}"
127
+ else:
128
+ raise FileNotFoundError(f"Can't find a valid installer to install {name}")
129
+ shell_wrapper(command)
130
+
131
+
105
132
  path_common_methods = {
106
133
  'cd': os.chdir,
107
134
  'cwd': lambda: os.getcwd(),
@@ -113,6 +140,8 @@ path_common_methods = {
113
140
  }
114
141
 
115
142
  default_methods = {
143
+ 'reduce': reduce,
144
+ 'chain': chain,
116
145
  'xeval': _xeval,
117
146
  'echo': lambda *x, **y: print(*x, **dict(flush=True) | y),
118
147
  'echos': lambda *x, **y: print(*x, **dict(end='', flush=True) | y),
@@ -121,6 +150,7 @@ default_methods = {
121
150
  'o2s': obj2str,
122
151
  'now': now,
123
152
  'getpass': getpass.getpass,
153
+ 'install': _install,
124
154
  'Path': Path,
125
155
  'path': {
126
156
  **path_common_methods,
@@ -149,6 +179,7 @@ default_methods = {
149
179
  'wf': write_file,
150
180
  'rt': read_text,
151
181
  'rf': read_file,
182
+ 'ci': copy_recurse_ignore,
152
183
 
153
184
  'sf': split_file,
154
185
  'sfr': remove_split_files,
@@ -158,6 +189,15 @@ default_methods = {
158
189
  'hash': lambda x, name='sha256', args=None: hash_file(name, x, args=args),
159
190
  },
160
191
  **path_common_methods,
192
+ 'pu': {
193
+ 'ps': process_list_all,
194
+ 'kill': process_kill,
195
+ 'pi': process_detail,
196
+ },
197
+
198
+ 'sys': {
199
+ 'utf8': lambda: sys.stdout.reconfigure(encoding='utf-8')
200
+ },
161
201
 
162
202
  'compress': compress_files,
163
203
  'decompress': decompress_files,
@@ -173,10 +213,17 @@ default_methods = {
173
213
  'notequal': lambda x, y: x != y,
174
214
  'beep': lambda x=True: sound_notify(x),
175
215
 
176
- 'invoke': lambda __not_use_this_var_name__, *args, **kwargs: InvokeMarker.execute_file(
177
- None, __not_use_this_var_name__, args, kwargs),
178
- 'goto': lambda __not_use_this_var_name__, *args, **kwargs: GotoMarker.execute_file(
179
- None, __not_use_this_var_name__, args, kwargs),
216
+ 'invoke': lambda __placeholder__filepath, *args, **kwargs: InvokeMarker.execute_file(
217
+ None, __placeholder__filepath, args, kwargs),
218
+ 'goto': lambda __placeholder__filepath, *args, **kwargs: GotoMarker.execute_file(
219
+ None, __placeholder__filepath, args, kwargs),
220
+
221
+ 'glob': {
222
+ 're': glob2re,
223
+ 'compile': glob_compile,
224
+ 'match': glob_match,
225
+ 'matcher': GeneralMatcher,
226
+ },
180
227
 
181
228
  'shlex': {
182
229
  'split': shlex_split,
@@ -188,4 +235,13 @@ default_methods = {
188
235
  'fetch': download_file,
189
236
  'download': download_from_http,
190
237
  },
238
+
239
+ 'git': {
240
+ 'apply': git_apply,
241
+ 'remotes': git_list_remotes,
242
+ 'modules': git_parse_modules,
243
+ 'fetch': git_fetch_min,
244
+ 'clean': git_clean_dir,
245
+ 'head': git_head,
246
+ }
191
247
  }
@@ -2,15 +2,21 @@ import os
2
2
  import sys
3
3
  import shutil
4
4
  import tempfile
5
+ import sysconfig
6
+ import platform
5
7
  from pathlib import Path
6
8
  from sysconfig import get_paths
7
9
  from importlib import metadata
10
+ from extra_platforms import current_os as extra_platforms_current_os
8
11
  from dektools.module import ModuleProxy
9
12
  from dektools.time import DateTime
13
+ from dektools.file import read_text
10
14
  from ...utils.serializer import serializer
11
15
  from ..redirect import shell_name
12
16
 
13
17
  current_shell = shutil.which(shell_name, path=get_paths()['scripts'])
18
+ current_os = extra_platforms_current_os()
19
+ user_is_root = "posix" in os.name and os.geteuid() == 0
14
20
 
15
21
 
16
22
  def make_shell_properties(shell):
@@ -54,6 +60,17 @@ default_properties = {
54
60
  'win': is_on_win,
55
61
  'ps': os.pathsep,
56
62
  },
63
+ 'platform': {
64
+ 'cygwin': sys.platform == 'cygwin',
65
+ 'mingw': sysconfig.get_platform() == 'mingw',
66
+ 'msys': sys.platform == 'msys',
67
+ 'wsl': 'Microsoft' in read_text('/proc/version', default=''),
68
+ 'windows': platform.system() == 'Windows',
69
+ 'macos': platform.system() == 'Darwin',
70
+ 'linux': platform.system() == 'Linux',
71
+ 'name': {'Windows': 'windows', 'Darwin': 'macos', 'Linux': 'linux'}.get(platform.system()),
72
+ 'entry': current_os,
73
+ },
57
74
  'path': {
58
75
  'root': Path(path_root),
59
76
  'home': Path(path_home),
@@ -12,10 +12,10 @@ from .function import *
12
12
  from .exec import *
13
13
  from .echo import *
14
14
  from .pip_ import *
15
- from .shell import *
15
+ from .commands import *
16
16
  from .redirect import *
17
17
  from .input import *
18
- from .timout import *
18
+ from .shell import *
19
19
  from .empty import *
20
20
 
21
21
 
@@ -39,12 +39,12 @@ def generate_markers(*args, **kwargs):
39
39
  EndMarker, BreakMarker, ContinueMarker,
40
40
  CommentMultiLineMarker, CommentMarker, CommentShebangMarker, CommentConfigMarker,
41
41
  PipMarker,
42
- ShellMarker,
42
+ CommandsMarker,
43
43
  RedirectMarker, ShiftMarker,
44
- TimeoutMarker,
44
+ TimeoutMarker, RetryMarker,
45
45
  IgnoreMarker,
46
46
  PrefixShellMarker,
47
- AssignCallMarker, AssignInvokerMarker, AssignGotoMarker, AssignTimeoutMarker,
47
+ AssignCallMarker, AssignInvokerMarker, AssignGotoMarker, AssignTimeoutMarker, AssignRetryMarker,
48
48
  AssignExecMarker, AssignEvalMarker, AssignCmdcallMarker,
49
49
  AssignMultiLineRawStrMarker, AssignMultiLineStrMarker, AssignRawStrMarker, AssignStrMarker,
50
50
  EmptyMarker, # must be at the tail
@@ -2,7 +2,7 @@ from .base import MarkerWithEnd
2
2
  from .empty import EmptyMarker
3
3
 
4
4
 
5
- class ShellMarker(MarkerWithEnd):
5
+ class CommandsMarker(MarkerWithEnd):
6
6
  tag_head = "@@"
7
7
  target_marker_cls = EmptyMarker
8
8
 
@@ -1,6 +1,6 @@
1
1
  import os
2
2
  from dektools.file import normal_path
3
- from ...utils.cmd import pack_context
3
+ from ...utils.cmd import pack_context_full
4
4
  from .base import MarkerBase
5
5
  from .base.core import get_inner_vars
6
6
 
@@ -18,7 +18,7 @@ class MarkerInvokerBase(MarkerBase):
18
18
  def execute_file(cls, marker_set, filepath, args, kwargs):
19
19
  if marker_set is None:
20
20
  marker_set = get_inner_vars('__inner_marker_set__')
21
- return cls._run_file(marker_set, normal_path(filepath), pack_context(args, kwargs))
21
+ return cls._run_file(marker_set, normal_path(filepath), pack_context_full(args, kwargs))
22
22
 
23
23
  @classmethod
24
24
  def _run_file(cls, marker_set, filepath, attrs):
@@ -28,7 +28,7 @@ class RedirectMarker(MarkerRedirect):
28
28
  shell_properties = make_shell_properties(path_shell)
29
29
  if shell_properties['shell'] != current_shell:
30
30
  fp = self.eval(context, "fp")
31
- fpp = os.path.dirname(fp).relace('/', os.sep)
31
+ fpp = os.path.dirname(fp).replace('/', os.sep)
32
32
  shell = shell_properties['sh']['rfc' if os.getcwd() == fpp else 'rf']
33
33
  args, kwargs = self.eval(context, f'({key_args}, {key_kwargs})')
34
34
  argv = ak2cmd(args, kwargs)
@@ -0,0 +1,56 @@
1
+ import subprocess
2
+ from dektools.shell import shell_timeout, shell_wrapper, shell_retry
3
+ from .empty import MarkerShell, ShellCommand
4
+
5
+
6
+ class TimeoutShellCommand(ShellCommand):
7
+ def shell(self, command, timeout=None, env=None, **kwargs):
8
+ try:
9
+ if timeout > 0:
10
+ return shell_timeout(command, timeout, env=env)
11
+ else:
12
+ return shell_wrapper(command, env=env)
13
+ except subprocess.SubprocessError as e:
14
+ return e
15
+
16
+
17
+ class TimeoutMarker(MarkerShell):
18
+ tag_head = "timeout"
19
+
20
+ shell_cls = TimeoutShellCommand
21
+
22
+ def execute(self, context, command, marker_node, marker_set):
23
+ _, timeout, command = self.split_raw(command, 2)
24
+ if command:
25
+ self.execute_core_timeout(context, command, marker_node, marker_set, timeout)
26
+
27
+ @classmethod
28
+ def execute_core_timeout(cls, context, command, marker_node, marker_set, timeout):
29
+ return cls.execute_core(context, command, marker_node, marker_set, dict(timeout=int(float(timeout))))
30
+
31
+
32
+ class RetryShellCommand(ShellCommand):
33
+ def shell(self, command, times=None, env=None, **kwargs):
34
+ try:
35
+ return shell_retry(command=command, times=times, env=env)
36
+ except subprocess.SubprocessError as e:
37
+ return e
38
+
39
+
40
+ class RetryMarker(MarkerShell):
41
+ tag_head = "retry"
42
+
43
+ shell_cls = RetryShellCommand
44
+
45
+ def execute(self, context, command, marker_node, marker_set):
46
+ _, times, command = self.split_raw(command, 2)
47
+ if command:
48
+ self.execute_core_retry(context, command, marker_node, marker_set, times)
49
+
50
+ @classmethod
51
+ def execute_core_retry(cls, context, command, marker_node, marker_set, times):
52
+ try:
53
+ times = int(float(times))
54
+ except ValueError:
55
+ times = None
56
+ return cls.execute_core(context, command, marker_node, marker_set, dict(times=times))
@@ -1,7 +1,7 @@
1
1
  import re
2
2
  from .base import MarkerBase, MarkerWithEnd, MarkerNoTranslator, cmd_call_prefix_simple
3
3
  from .function import CallMarker
4
- from .timout import TimeoutMarker
4
+ from .shell import TimeoutMarker, RetryMarker
5
5
  from .invoke import MarkerInvokerBase, InvokeMarker, GotoMarker
6
6
 
7
7
 
@@ -114,6 +114,15 @@ class AssignTimeoutMarker(MarkerAssignValueBase, TimeoutMarker):
114
114
  return self.execute_core_timeout(context, expression, marker_node, marker_set, timeout)
115
115
 
116
116
 
117
+ class AssignRetryMarker(MarkerAssignValueBase, RetryMarker):
118
+ tag_head = None
119
+ tag_head_re_args = r'retry[ \t\f\r\n]+'
120
+
121
+ def get_value(self, context, marker_node, marker_set, expression):
122
+ times, expression = self.split_raw(expression, 1)
123
+ return self.execute_core_retry(context, expression, marker_node, marker_set, times)
124
+
125
+
117
126
  class DelVarMarker(MarkerBase):
118
127
  tag_head = "del"
119
128
 
@@ -34,7 +34,7 @@ def ak2cmd(args, kwargs=None):
34
34
 
35
35
 
36
36
  def pack_context(args, kwargs):
37
- return {f'{key_arg}{i}': arg for i, arg in enumerate(args)} | {key_args: args, key_kwargs: kwargs} | kwargs
37
+ return {f'{key_arg}{i}': arg for i, arg in enumerate(args)} | {key_args: tuple(args), key_kwargs: kwargs} | kwargs
38
38
 
39
39
 
40
40
  def pack_context_argv():
@@ -1,13 +1,14 @@
1
1
  [project]
2
2
  name = "dekshell"
3
- version = "0.1.99"
3
+ version = "0.2.6"
4
4
  description = ""
5
5
  authors = [
6
6
  { name = "sanzenwin", email = "sanzenwin@gmail.com" },
7
7
  ]
8
8
  dependencies = [
9
9
  "packaging<=23.1",
10
- "dektools[date,fetch]<1.0.0",
10
+ "extra-platforms<=3.1.0",
11
+ "dektools[ignore,date,fetch,ps,tab]<1.0.0",
11
12
  "dekmedia[audio]<1.0.0",
12
13
  ]
13
14
  requires-python = ">=3.8"
@@ -1,26 +0,0 @@
1
- import subprocess
2
- from dektools.shell import shell_timeout
3
- from .empty import MarkerShell, ShellCommand
4
-
5
-
6
- class TimeoutShellCommand(ShellCommand):
7
- def shell(self, command, timeout=None, env=None, **kwargs):
8
- try:
9
- return shell_timeout(command, timeout, env=env, check=True)
10
- except subprocess.CalledProcessError as e:
11
- return e
12
-
13
-
14
- class TimeoutMarker(MarkerShell):
15
- tag_head = "timeout"
16
-
17
- shell_cls = TimeoutShellCommand
18
-
19
- def execute(self, context, command, marker_node, marker_set):
20
- _, timeout, command = self.split_raw(command, 2)
21
- if command:
22
- self.execute_core_timeout(context, command, marker_node, marker_set, timeout)
23
-
24
- @classmethod
25
- def execute_core_timeout(cls, context, command, marker_node, marker_set, timeout):
26
- return cls.execute_core(context, command, marker_node, marker_set, dict(timeout=int(float(timeout))))
File without changes
File without changes