From 5fb648524c8fc551f15dccf2a47104aeb3da258f Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Thu, 25 Apr 2024 18:53:28 +0200 Subject: [PATCH 01/39] FuncAlias --- news/aliases_imp.rst | 23 ++++++++++++++++ tests/test_aliases.py | 5 ++-- xonsh/aliases.py | 62 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 news/aliases_imp.rst diff --git a/news/aliases_imp.rst b/news/aliases_imp.rst new file mode 100644 index 0000000000..c694bbefcd --- /dev/null +++ b/news/aliases_imp.rst @@ -0,0 +1,23 @@ +**Added:** + +* Added FuncAlias to process callable aliases. + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/tests/test_aliases.py b/tests/test_aliases.py index da2b1eac10..a80b31b9b3 100644 --- a/tests/test_aliases.py +++ b/tests/test_aliases.py @@ -9,7 +9,7 @@ from xonsh.aliases import Aliases, ExecAlias -def cd(args, stdin=None, **kwargs): +def cd(args, stdin=None): return args @@ -30,10 +30,11 @@ def test_imports(xession): "o": ["omg", "lala"], "ls": ["ls", "- -"], "color_ls": ["ls", "--color=true"], - "cd": cd, + "cd": 'FuncAlias2', "indirect_cd": ["cd", ".."], } raw = ales._raw + raw['cd'] = type(ales['cd']).__name__ assert raw == expected diff --git a/xonsh/aliases.py b/xonsh/aliases.py index e1b59c9f17..a2308f5299 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -40,6 +40,7 @@ argvquote, escape_windows_cmd_string, print_color, + print_exception, strip_simple_quotes, swap_values, to_repr_pretty_, @@ -54,6 +55,62 @@ def EXEC_ALIAS_RE(): return re.compile(r"@\(|\$\(|!\(|\$\[|!\[|\&\&|\|\||\s+and\s+|\s+or\s+|[>|<]") +class FuncAlias: + attributes = ['__xonsh_threadable__', '__xonsh_capturable__'] + + def __init__(self, name, func): + self.__name__ = self.name = name + self.func = func + for attr in self.attributes: + if (val := getattr(func, attr, None)) is not None: + self.__setattr__(attr, val) + + def run(self, *args, **kwargs): + try: + return self.func(*args, **kwargs) + except Exception as e: + print_exception(f'Exception in {repr(self)}') + + def __repr__(self): + r = {"name": self.name, "func": self.func} + for attr in self.attributes: + if (val := getattr(self, attr, None)) is not None: + r[attr] = val + return f"FuncAlias({repr(r)})" + + +class FuncAlias0(FuncAlias): + def __call__(self): + return self.run() + +class FuncAlias1(FuncAlias): + def __call__(self, args=None): + return self.run(args) + +class FuncAlias2(FuncAlias): + def __call__(self, args=None, stdin=None): + return self.run(args, stdin) + +class FuncAlias3(FuncAlias): + def __call__(self, args=None, stdin=None, stdout=None): + return self.run(args, stdin, stdout) + +class FuncAlias4(FuncAlias): + def __call__(self, args=None, stdin=None, stdout=None, stderr=None): + return self.run(args, stdin, stdout, stderr) + +class FuncAlias5(FuncAlias): + def __call__(self, args=None, stdin=None, stdout=None, stderr=None, spec=None): + return self.run(args, stdin, stdout, stderr, spec) + +class FuncAlias6(FuncAlias): + def __call__(self, args=None, stdin=None, stdout=None, stderr=None, spec=None, stack=None): + return self.run(args, stdin, stdout, stderr, spec, stack) + + +FUNC_ALIAS_CLASSES = [FuncAlias0, FuncAlias1, FuncAlias2, FuncAlias3, FuncAlias4, FuncAlias5, FuncAlias6] + + class Aliases(cabc.MutableMapping): """Represents a location to hold and look up aliases.""" @@ -182,6 +239,9 @@ def __setitem__(self, key, val): else: # need to exec alias self._raw[key] = ExecAlias(val, filename=f) + elif isinstance(val, types.FunctionType): + nargs = len(inspect.signature(val).parameters.items()) + self._raw[key] = FUNC_ALIAS_CLASSES[nargs](key, val) else: self._raw[key] = val @@ -225,7 +285,7 @@ def __repr__(self): class ExecAlias: - """Provides a callable alias for xonsh source code.""" + """Provides an exec alias for xonsh source code.""" def __init__(self, src, filename=""): """ From 2dcc6f9d361e1a5d55476695669e0901bd6b87c7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 16:59:12 +0000 Subject: [PATCH 02/39] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_aliases.py | 4 ++-- xonsh/aliases.py | 26 +++++++++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/tests/test_aliases.py b/tests/test_aliases.py index a80b31b9b3..fd0fd38e84 100644 --- a/tests/test_aliases.py +++ b/tests/test_aliases.py @@ -30,11 +30,11 @@ def test_imports(xession): "o": ["omg", "lala"], "ls": ["ls", "- -"], "color_ls": ["ls", "--color=true"], - "cd": 'FuncAlias2', + "cd": "FuncAlias2", "indirect_cd": ["cd", ".."], } raw = ales._raw - raw['cd'] = type(ales['cd']).__name__ + raw["cd"] = type(ales["cd"]).__name__ assert raw == expected diff --git a/xonsh/aliases.py b/xonsh/aliases.py index a2308f5299..655d19c0e6 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -56,7 +56,7 @@ def EXEC_ALIAS_RE(): class FuncAlias: - attributes = ['__xonsh_threadable__', '__xonsh_capturable__'] + attributes = ["__xonsh_threadable__", "__xonsh_capturable__"] def __init__(self, name, func): self.__name__ = self.name = name @@ -68,8 +68,8 @@ def __init__(self, name, func): def run(self, *args, **kwargs): try: return self.func(*args, **kwargs) - except Exception as e: - print_exception(f'Exception in {repr(self)}') + except Exception: + print_exception(f"Exception in {repr(self)}") def __repr__(self): r = {"name": self.name, "func": self.func} @@ -83,32 +83,48 @@ class FuncAlias0(FuncAlias): def __call__(self): return self.run() + class FuncAlias1(FuncAlias): def __call__(self, args=None): return self.run(args) + class FuncAlias2(FuncAlias): def __call__(self, args=None, stdin=None): return self.run(args, stdin) + class FuncAlias3(FuncAlias): def __call__(self, args=None, stdin=None, stdout=None): return self.run(args, stdin, stdout) + class FuncAlias4(FuncAlias): def __call__(self, args=None, stdin=None, stdout=None, stderr=None): return self.run(args, stdin, stdout, stderr) + class FuncAlias5(FuncAlias): def __call__(self, args=None, stdin=None, stdout=None, stderr=None, spec=None): return self.run(args, stdin, stdout, stderr, spec) + class FuncAlias6(FuncAlias): - def __call__(self, args=None, stdin=None, stdout=None, stderr=None, spec=None, stack=None): + def __call__( + self, args=None, stdin=None, stdout=None, stderr=None, spec=None, stack=None + ): return self.run(args, stdin, stdout, stderr, spec, stack) -FUNC_ALIAS_CLASSES = [FuncAlias0, FuncAlias1, FuncAlias2, FuncAlias3, FuncAlias4, FuncAlias5, FuncAlias6] +FUNC_ALIAS_CLASSES = [ + FuncAlias0, + FuncAlias1, + FuncAlias2, + FuncAlias3, + FuncAlias4, + FuncAlias5, + FuncAlias6, +] class Aliases(cabc.MutableMapping): From 12322eb0f47c3b2e8ad9948d487f83f86e6367e4 Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Thu, 25 Apr 2024 19:14:53 +0200 Subject: [PATCH 03/39] FuncAlias --- xonsh/aliases.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xonsh/aliases.py b/xonsh/aliases.py index 655d19c0e6..d7923f29d1 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -56,6 +56,8 @@ def EXEC_ALIAS_RE(): class FuncAlias: + """Provides a callable alias for xonsh commands.""" + attributes = ["__xonsh_threadable__", "__xonsh_capturable__"] def __init__(self, name, func): From d7a4af7ca04408f93711eba8439eaa864ff04ae1 Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Sat, 27 Apr 2024 20:48:05 +0200 Subject: [PATCH 04/39] wip --- xonsh/aliases.py | 58 +++++------------------------------------------- 1 file changed, 6 insertions(+), 52 deletions(-) diff --git a/xonsh/aliases.py b/xonsh/aliases.py index d7923f29d1..2dffff5237 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -67,12 +67,6 @@ def __init__(self, name, func): if (val := getattr(func, attr, None)) is not None: self.__setattr__(attr, val) - def run(self, *args, **kwargs): - try: - return self.func(*args, **kwargs) - except Exception: - print_exception(f"Exception in {repr(self)}") - def __repr__(self): r = {"name": self.name, "func": self.func} for attr in self.attributes: @@ -80,53 +74,14 @@ def __repr__(self): r[attr] = val return f"FuncAlias({repr(r)})" - -class FuncAlias0(FuncAlias): - def __call__(self): - return self.run() - - -class FuncAlias1(FuncAlias): - def __call__(self, args=None): - return self.run(args) - - -class FuncAlias2(FuncAlias): - def __call__(self, args=None, stdin=None): - return self.run(args, stdin) - - -class FuncAlias3(FuncAlias): - def __call__(self, args=None, stdin=None, stdout=None): - return self.run(args, stdin, stdout) - - -class FuncAlias4(FuncAlias): - def __call__(self, args=None, stdin=None, stdout=None, stderr=None): - return self.run(args, stdin, stdout, stderr) - - -class FuncAlias5(FuncAlias): - def __call__(self, args=None, stdin=None, stdout=None, stderr=None, spec=None): - return self.run(args, stdin, stdout, stderr, spec) - - -class FuncAlias6(FuncAlias): def __call__( self, args=None, stdin=None, stdout=None, stderr=None, spec=None, stack=None ): - return self.run(args, stdin, stdout, stderr, spec, stack) - - -FUNC_ALIAS_CLASSES = [ - FuncAlias0, - FuncAlias1, - FuncAlias2, - FuncAlias3, - FuncAlias4, - FuncAlias5, - FuncAlias6, -] + try: + func_args = [args, stdin, stdout, stderr, spec, stack][:len(inspect.signature(self.func).parameters)] + return self.func(*func_args) + except Exception: + print_exception(f"Exception in {repr(self)}") class Aliases(cabc.MutableMapping): @@ -258,8 +213,7 @@ def __setitem__(self, key, val): # need to exec alias self._raw[key] = ExecAlias(val, filename=f) elif isinstance(val, types.FunctionType): - nargs = len(inspect.signature(val).parameters.items()) - self._raw[key] = FUNC_ALIAS_CLASSES[nargs](key, val) + self._raw[key] = FuncAlias(key, val) else: self._raw[key] = val From 0ddbca037be0d21747551ba2bb1e4d4d9b6b402e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 27 Apr 2024 18:48:20 +0000 Subject: [PATCH 05/39] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xonsh/aliases.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xonsh/aliases.py b/xonsh/aliases.py index 2dffff5237..2494aa6bfc 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -78,7 +78,9 @@ def __call__( self, args=None, stdin=None, stdout=None, stderr=None, spec=None, stack=None ): try: - func_args = [args, stdin, stdout, stderr, spec, stack][:len(inspect.signature(self.func).parameters)] + func_args = [args, stdin, stdout, stderr, spec, stack][ + : len(inspect.signature(self.func).parameters) + ] return self.func(*func_args) except Exception: print_exception(f"Exception in {repr(self)}") From 8f58a2fe837b058f21df337e3bcba9aabc5922ca Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Sat, 27 Apr 2024 20:55:49 +0200 Subject: [PATCH 06/39] wip --- tests/test_aliases.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_aliases.py b/tests/test_aliases.py index fd0fd38e84..a2c0e45a34 100644 --- a/tests/test_aliases.py +++ b/tests/test_aliases.py @@ -30,7 +30,7 @@ def test_imports(xession): "o": ["omg", "lala"], "ls": ["ls", "- -"], "color_ls": ["ls", "--color=true"], - "cd": "FuncAlias2", + "cd": "FuncAlias", "indirect_cd": ["cd", ".."], } raw = ales._raw From 6893614da0b6782db8b7023831bfc5a48dd63324 Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Sat, 27 Apr 2024 20:56:12 +0200 Subject: [PATCH 07/39] update From daf7f18fd2c869820124aaddbf1518e578584742 Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Sat, 27 Apr 2024 21:42:31 +0200 Subject: [PATCH 08/39] wip --- xonsh/procs/specs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xonsh/procs/specs.py b/xonsh/procs/specs.py index 64705a464d..3448bf68e7 100644 --- a/xonsh/procs/specs.py +++ b/xonsh/procs/specs.py @@ -699,7 +699,7 @@ def resolve_stack(self): if not callable(self.alias): return # check that we actual need the stack - sig = inspect.signature(self.alias) + sig = inspect.signature(getattr(self.alias, 'func', self.alias)) if len(sig.parameters) <= 5 and "stack" not in sig.parameters: return # compute the stack, and filter out these build methods From 49732d36814518144ddb9d9e5ced57f033c0215e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 27 Apr 2024 19:43:19 +0000 Subject: [PATCH 09/39] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xonsh/procs/specs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xonsh/procs/specs.py b/xonsh/procs/specs.py index 3448bf68e7..d5a92573a4 100644 --- a/xonsh/procs/specs.py +++ b/xonsh/procs/specs.py @@ -699,7 +699,7 @@ def resolve_stack(self): if not callable(self.alias): return # check that we actual need the stack - sig = inspect.signature(getattr(self.alias, 'func', self.alias)) + sig = inspect.signature(getattr(self.alias, "func", self.alias)) if len(sig.parameters) <= 5 and "stack" not in sig.parameters: return # compute the stack, and filter out these build methods From 87b59f9b6e7a5b4b1d898077b362e615bb90fb92 Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Sat, 27 Apr 2024 21:46:01 +0200 Subject: [PATCH 10/39] wip --- xonsh/aliases.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/xonsh/aliases.py b/xonsh/aliases.py index 2494aa6bfc..29eec59a5d 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -69,9 +69,7 @@ def __init__(self, name, func): def __repr__(self): r = {"name": self.name, "func": self.func} - for attr in self.attributes: - if (val := getattr(self, attr, None)) is not None: - r[attr] = val + r |= {attr: val for attr in self.attributes if (val := getattr(self, attr, None)) is not None} return f"FuncAlias({repr(r)})" def __call__( From a95de7f334d32c5950a03d0b7f2b93257d22c5c1 Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Sat, 27 Apr 2024 21:46:18 +0200 Subject: [PATCH 11/39] update From 226ef6fc4c4d903da96124cedfb7e7fc83256c45 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 27 Apr 2024 19:46:33 +0000 Subject: [PATCH 12/39] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xonsh/aliases.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/xonsh/aliases.py b/xonsh/aliases.py index 29eec59a5d..ea1a624f02 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -69,7 +69,11 @@ def __init__(self, name, func): def __repr__(self): r = {"name": self.name, "func": self.func} - r |= {attr: val for attr in self.attributes if (val := getattr(self, attr, None)) is not None} + r |= { + attr: val + for attr in self.attributes + if (val := getattr(self, attr, None)) is not None + } return f"FuncAlias({repr(r)})" def __call__( From bf12f6242c87fb913efae4a3d164f6570976b012 Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Mon, 29 Apr 2024 23:24:30 +0200 Subject: [PATCH 13/39] inherit __doc__ --- xonsh/aliases.py | 7 ++++--- xonsh/procs/specs.py | 14 +++++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/xonsh/aliases.py b/xonsh/aliases.py index ea1a624f02..1489c14ebe 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -58,12 +58,13 @@ def EXEC_ALIAS_RE(): class FuncAlias: """Provides a callable alias for xonsh commands.""" - attributes = ["__xonsh_threadable__", "__xonsh_capturable__"] + attributes_inherit = ["__xonsh_threadable__", "__xonsh_capturable__", "__doc__"] + attributes_show = ["__xonsh_threadable__", "__xonsh_capturable__"] def __init__(self, name, func): self.__name__ = self.name = name self.func = func - for attr in self.attributes: + for attr in self.attributes_inherit: if (val := getattr(func, attr, None)) is not None: self.__setattr__(attr, val) @@ -71,7 +72,7 @@ def __repr__(self): r = {"name": self.name, "func": self.func} r |= { attr: val - for attr in self.attributes + for attr in self.attributes_show if (val := getattr(self, attr, None)) is not None } return f"FuncAlias({repr(r)})" diff --git a/xonsh/procs/specs.py b/xonsh/procs/specs.py index d5a92573a4..98d5ff62cc 100644 --- a/xonsh/procs/specs.py +++ b/xonsh/procs/specs.py @@ -488,10 +488,18 @@ def _run_binary(self, kwargs): except FileNotFoundError as ex: cmd0 = self.cmd[0] if len(self.cmd) == 1 and cmd0.endswith("?"): - with contextlib.suppress(OSError): + cmdq = cmd0.rstrip("?") + if cmdq in XSH.aliases: + alias = XSH.aliases[cmdq] + descr = repr(alias) + (':\n'+ doc) if (doc := getattr(alias, '__doc__', '')) else '' return self.cls( - ["man", cmd0.rstrip("?")], bufsize=bufsize, **kwargs - ) + ['echo', descr], bufsize=bufsize, **kwargs + ) + else: + with contextlib.suppress(OSError): + return self.cls( + ["man", cmdq], bufsize=bufsize, **kwargs + ) e = f"xonsh: subprocess mode: command not found: {repr(cmd0)}" env = XSH.env sug = xt.suggest_commands(cmd0, env) From 330fa121d1f3276b2ebf293fbe9d5268112a49d8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 21:24:45 +0000 Subject: [PATCH 14/39] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xonsh/procs/specs.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/xonsh/procs/specs.py b/xonsh/procs/specs.py index 98d5ff62cc..2b2de92ef6 100644 --- a/xonsh/procs/specs.py +++ b/xonsh/procs/specs.py @@ -491,15 +491,15 @@ def _run_binary(self, kwargs): cmdq = cmd0.rstrip("?") if cmdq in XSH.aliases: alias = XSH.aliases[cmdq] - descr = repr(alias) + (':\n'+ doc) if (doc := getattr(alias, '__doc__', '')) else '' - return self.cls( - ['echo', descr], bufsize=bufsize, **kwargs - ) + descr = ( + repr(alias) + (":\n" + doc) + if (doc := getattr(alias, "__doc__", "")) + else "" + ) + return self.cls(["echo", descr], bufsize=bufsize, **kwargs) else: with contextlib.suppress(OSError): - return self.cls( - ["man", cmdq], bufsize=bufsize, **kwargs - ) + return self.cls(["man", cmdq], bufsize=bufsize, **kwargs) e = f"xonsh: subprocess mode: command not found: {repr(cmd0)}" env = XSH.env sug = xt.suggest_commands(cmd0, env) From aa4cd8c9df87ab7743a865cfcecb1e2cf9ce40ed Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Mon, 6 May 2024 16:34:23 +0200 Subject: [PATCH 15/39] wip --- xonsh/procs/proxies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xonsh/procs/proxies.py b/xonsh/procs/proxies.py index bc9b076722..8fa7fddb32 100644 --- a/xonsh/procs/proxies.py +++ b/xonsh/procs/proxies.py @@ -274,7 +274,7 @@ def parse_proxy_return(r, stdout, stderr): stdout.write(str(r[0])) stdout.flush() if rlen > 1 and r[1] is not None: - stderr.write(str(r[1])) + stderr.write(str(r[1])+"\n") stderr.flush() if rlen > 2 and isinstance(r[2], int): cmd_result = r[2] From 67f3bfa014cd26c8fc8683baeb0dc1977f1122e4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 14:35:07 +0000 Subject: [PATCH 16/39] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xonsh/procs/proxies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xonsh/procs/proxies.py b/xonsh/procs/proxies.py index 8fa7fddb32..095a41cb8d 100644 --- a/xonsh/procs/proxies.py +++ b/xonsh/procs/proxies.py @@ -274,7 +274,7 @@ def parse_proxy_return(r, stdout, stderr): stdout.write(str(r[0])) stdout.flush() if rlen > 1 and r[1] is not None: - stderr.write(str(r[1])+"\n") + stderr.write(str(r[1]) + "\n") stderr.flush() if rlen > 2 and isinstance(r[2], int): cmd_result = r[2] From 615448026b28a6f05a6ded09ec3433979af60b50 Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Mon, 6 May 2024 16:37:13 +0200 Subject: [PATCH 17/39] wip --- xonsh/procs/proxies.py | 2 +- xonsh/tools.py | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/xonsh/procs/proxies.py b/xonsh/procs/proxies.py index 8fa7fddb32..6a9cc903f6 100644 --- a/xonsh/procs/proxies.py +++ b/xonsh/procs/proxies.py @@ -274,7 +274,7 @@ def parse_proxy_return(r, stdout, stderr): stdout.write(str(r[0])) stdout.flush() if rlen > 1 and r[1] is not None: - stderr.write(str(r[1])+"\n") + stderr.write(xt.endswith_newline(str(r[1]))) stderr.flush() if rlen > 2 and isinstance(r[2], int): cmd_result = r[2] diff --git a/xonsh/tools.py b/xonsh/tools.py index 6662400e6b..16fa2c0821 100644 --- a/xonsh/tools.py +++ b/xonsh/tools.py @@ -2858,3 +2858,8 @@ def unquote(s: str, chars="'\""): if len(s) >= 2 and s[0] == s[-1] and s[0] in chars: return s[1:-1] return s + + +def endswith_newline(s : str): + """Add new line character to string if needed.""" + return s if s.endswith("\n") else (s + "\n") \ No newline at end of file From 312ed425b280e6060eaca2335a6e6d957bd0956e Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Mon, 6 May 2024 16:38:51 +0200 Subject: [PATCH 18/39] update From 8cf976244bc6795055bf4b987b6437238cd78a83 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 14:39:55 +0000 Subject: [PATCH 19/39] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xonsh/tools.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xonsh/tools.py b/xonsh/tools.py index 16fa2c0821..e04d8af279 100644 --- a/xonsh/tools.py +++ b/xonsh/tools.py @@ -2860,6 +2860,6 @@ def unquote(s: str, chars="'\""): return s -def endswith_newline(s : str): +def endswith_newline(s: str): """Add new line character to string if needed.""" - return s if s.endswith("\n") else (s + "\n") \ No newline at end of file + return s if s.endswith("\n") else (s + "\n") From a9e0595f622e3204400f112f52dea07bbfc78101 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 20:20:34 +0200 Subject: [PATCH 20/39] [pre-commit.ci] pre-commit autoupdate (#5397) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.4.2 → v0.4.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.2...v0.4.3) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 19d712b2ae..8b2d9e9b99 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ default_language_version: repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: 'v0.4.2' + rev: 'v0.4.3' hooks: - id: ruff args: [., --fix, --exit-non-zero-on-fix] From 4eef469bc346a82e8dd83030545225a672ee561f Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Mon, 6 May 2024 16:38:51 +0200 Subject: [PATCH 21/39] update From 51c5c3748aecb87817bec81740c3ca3eaa0643f6 Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Tue, 7 May 2024 16:02:49 +0200 Subject: [PATCH 22/39] update From 75bc38992825845dfa0003d1a0696ee348df1537 Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Tue, 7 May 2024 16:08:31 +0200 Subject: [PATCH 23/39] removed partial_proxy --- xonsh/procs/proxies.py | 69 ++---------------------------------------- 1 file changed, 2 insertions(+), 67 deletions(-) diff --git a/xonsh/procs/proxies.py b/xonsh/procs/proxies.py index 6a9cc903f6..6f4c5edf78 100644 --- a/xonsh/procs/proxies.py +++ b/xonsh/procs/proxies.py @@ -285,69 +285,6 @@ def parse_proxy_return(r, stdout, stderr): return cmd_result -def proxy_zero(f, args, stdin, stdout, stderr, spec, stack): - """Calls a proxy function which takes no parameters.""" - return f() - - -def proxy_one(f, args, stdin, stdout, stderr, spec, stack): - """Calls a proxy function which takes one parameter: args""" - return f(args) - - -def proxy_two(f, args, stdin, stdout, stderr, spec, stack): - """Calls a proxy function which takes two parameter: args and stdin.""" - return f(args, stdin) - - -def proxy_three(f, args, stdin, stdout, stderr, spec, stack): - """Calls a proxy function which takes three parameter: args, stdin, stdout.""" - return f(args, stdin, stdout) - - -def proxy_four(f, args, stdin, stdout, stderr, spec, stack): - """Calls a proxy function which takes four parameter: args, stdin, stdout, - and stderr. - """ - return f(args, stdin, stdout, stderr) - - -def proxy_five(f, args, stdin, stdout, stderr, spec, stack): - """Calls a proxy function which takes four parameter: args, stdin, stdout, - stderr, and spec. - """ - return f(args, stdin, stdout, stderr, spec) - - -PROXIES = (proxy_zero, proxy_one, proxy_two, proxy_three, proxy_four, proxy_five) - - -def partial_proxy(f): - """Dispatches the appropriate proxy function based on the number of args.""" - numargs = 0 - - for name, param in inspect.signature(f).parameters.items(): - # handle *args/**kwargs signature - if param.kind in {param.VAR_KEYWORD, param.VAR_POSITIONAL}: - numargs = 6 - break - if ( - param.kind == param.POSITIONAL_ONLY - or param.kind == param.POSITIONAL_OR_KEYWORD - ): - numargs += 1 - elif name in xt.ALIAS_KWARG_NAMES and param.kind == param.KEYWORD_ONLY: - numargs += 1 - if numargs < 6: - return functools.partial(PROXIES[numargs], f) - elif numargs == 6: - # don't need to partial. - return f - else: - e = "Expected proxy with 6 or fewer arguments for {}, not {}" - raise xt.XonshError(e.format(", ".join(xt.ALIAS_KWARG_NAMES), numargs)) - - def get_proc_proxy_name(cls): func_name = cls.f if type(cls.f) is functools.partial: @@ -409,8 +346,7 @@ def __init__( env : Mapping, optional Environment mapping. """ - self.orig_f = f - self.f = partial_proxy(f) + self.f = f self.args = args self.pid = None self.returncode = None @@ -799,8 +735,7 @@ def __init__( close_fds=False, env=None, ): - self.orig_f = f - self.f = partial_proxy(f) + self.f = f self.args = args self.pid = os.getpid() self.returncode = None From c77ff660eb3d608ef4d60ae360484aa264638b6d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 14:08:48 +0000 Subject: [PATCH 24/39] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xonsh/procs/proxies.py | 1 - 1 file changed, 1 deletion(-) diff --git a/xonsh/procs/proxies.py b/xonsh/procs/proxies.py index 6f4c5edf78..dcb1d0e8eb 100644 --- a/xonsh/procs/proxies.py +++ b/xonsh/procs/proxies.py @@ -9,7 +9,6 @@ import collections.abc as cabc import functools -import inspect import io import os import signal From 9f8b7cd1dfbd411c1dcbf3e23e65f606b084cac2 Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Tue, 7 May 2024 22:04:15 +0200 Subject: [PATCH 25/39] test --- tests/test_integrations.py | 46 ++++++++++++++++++++++++++++++++++++++ xonsh/aliases.py | 5 ++++- xonsh/tools.py | 9 ++++---- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/tests/test_integrations.py b/tests/test_integrations.py index deccff8bf3..6536d1bcf4 100644 --- a/tests/test_integrations.py +++ b/tests/test_integrations.py @@ -1000,6 +1000,52 @@ def test_run_fail_not_on_path(): assert out != "Hello world" +ALIASES_PRINT_CASES = [ + ( +""" +$RAISE_SUBPROC_ERROR = False +$XONSH_SHOW_TRACEBACK = False +aliases['f'] = lambda: 1/0 +echo f1f1f1 ; f ; echo f2f2f2 +""", +"^f1f1f1\nZeroDivisionError: .*\nException in FuncAlias(.*)\nf2f2f2\n$" + ), + ( +""" +$RAISE_SUBPROC_ERROR = True +$XONSH_SHOW_TRACEBACK = False +aliases['f'] = lambda: 1/0 +echo f1f1f1 ; f ; echo f2f2f2 +""", +"f1f1f1\nException in thread.*\nZeroDivisionError: .*\nsubprocess.CalledProcessError.*\n$" + ), + ( +""" +$RAISE_SUBPROC_ERROR = True +$XONSH_SHOW_TRACEBACK = True +aliases['f'] = lambda: 1/0 +echo f1f1f1 ; f ; echo f2f2f2 +""", +"f1f1f1\nException in thread.*\nTraceback.*\nZeroDivisionError: .*\nsubprocess.CalledProcessError.*\n$" + ), + ( +""" +$RAISE_SUBPROC_ERROR = False +$XONSH_SHOW_TRACEBACK = True +aliases['f'] = lambda: 1/0 +echo f1f1f1 ; f ; echo f2f2f2 +""", +"f1f1f1\n.*\nTraceback.*\nZeroDivisionError: .*\nException in FuncAlias(.*)\nf2f2f2\n$" + ), + +] +@pytest.mark.parametrize("case", ALIASES_PRINT_CASES) +def test_aliases_print(case): + cmd, match = case + out, err, ret = run_xonsh(cmd=cmd, single_command=False) + assert re.match(match, out, re.MULTILINE | re.DOTALL), f"\nFailed:\n```\n{cmd.strip()}\n```,\nresult: {out!r}\nexpected: {match!r}." + + @skip_if_on_windows @pytest.mark.parametrize("interactive", [True, False]) def test_raise_subproc_error_with_show_traceback(monkeypatch, interactive): diff --git a/xonsh/aliases.py b/xonsh/aliases.py index 1489c14ebe..20705825f0 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -86,7 +86,10 @@ def __call__( ] return self.func(*func_args) except Exception: - print_exception(f"Exception in {repr(self)}") + if XSH.env.get("RAISE_SUBPROC_ERROR", True): + raise + else: + print_exception(f"Exception in {repr(self)}") class Aliases(cabc.MutableMapping): diff --git a/xonsh/tools.py b/xonsh/tools.py index e04d8af279..764b8d0fe5 100644 --- a/xonsh/tools.py +++ b/xonsh/tools.py @@ -1116,7 +1116,7 @@ def display_colored_error_message(exc_info, strip_xonsh_error_types=True, limit= content = traceback.format_exception(*exc_info, limit=limit) if no_trace_and_raise_subproc_error and "Error:" in content[-1]: - content = [content[-1].rstrip()] + content = [content[-1]] traceback_str = "".join([v for v in content]) @@ -1129,11 +1129,10 @@ def display_colored_error_message(exc_info, strip_xonsh_error_types=True, limit= return import pygments.lexers.python - lexer = pygments.lexers.python.PythonTracebackLexer() tokens = list(pygments.lex(traceback_str, lexer=lexer)) # this goes to stdout, but since we are interactive it doesn't matter - print_color(tokens, end="\n", file=sys.stderr) + print_color(tokens, end="", file=sys.stderr) return @@ -2861,5 +2860,5 @@ def unquote(s: str, chars="'\""): def endswith_newline(s: str): - """Add new line character to string if needed.""" - return s if s.endswith("\n") else (s + "\n") + """Force one new line character end to string.""" + return s.rstrip("\n") + "\n" From 1fbca907e8cc738922f677834dbf272a3cfdbcb5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 20:05:51 +0000 Subject: [PATCH 26/39] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_integrations.py | 23 +++++++++++++---------- xonsh/tools.py | 1 + 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/tests/test_integrations.py b/tests/test_integrations.py index 6536d1bcf4..030a191fe2 100644 --- a/tests/test_integrations.py +++ b/tests/test_integrations.py @@ -1002,48 +1002,51 @@ def test_run_fail_not_on_path(): ALIASES_PRINT_CASES = [ ( -""" + """ $RAISE_SUBPROC_ERROR = False $XONSH_SHOW_TRACEBACK = False aliases['f'] = lambda: 1/0 echo f1f1f1 ; f ; echo f2f2f2 """, -"^f1f1f1\nZeroDivisionError: .*\nException in FuncAlias(.*)\nf2f2f2\n$" + "^f1f1f1\nZeroDivisionError: .*\nException in FuncAlias(.*)\nf2f2f2\n$", ), ( -""" + """ $RAISE_SUBPROC_ERROR = True $XONSH_SHOW_TRACEBACK = False aliases['f'] = lambda: 1/0 echo f1f1f1 ; f ; echo f2f2f2 """, -"f1f1f1\nException in thread.*\nZeroDivisionError: .*\nsubprocess.CalledProcessError.*\n$" + "f1f1f1\nException in thread.*\nZeroDivisionError: .*\nsubprocess.CalledProcessError.*\n$", ), ( -""" + """ $RAISE_SUBPROC_ERROR = True $XONSH_SHOW_TRACEBACK = True aliases['f'] = lambda: 1/0 echo f1f1f1 ; f ; echo f2f2f2 """, -"f1f1f1\nException in thread.*\nTraceback.*\nZeroDivisionError: .*\nsubprocess.CalledProcessError.*\n$" + "f1f1f1\nException in thread.*\nTraceback.*\nZeroDivisionError: .*\nsubprocess.CalledProcessError.*\n$", ), ( -""" + """ $RAISE_SUBPROC_ERROR = False $XONSH_SHOW_TRACEBACK = True aliases['f'] = lambda: 1/0 echo f1f1f1 ; f ; echo f2f2f2 """, -"f1f1f1\n.*\nTraceback.*\nZeroDivisionError: .*\nException in FuncAlias(.*)\nf2f2f2\n$" + "f1f1f1\n.*\nTraceback.*\nZeroDivisionError: .*\nException in FuncAlias(.*)\nf2f2f2\n$", ), - ] + + @pytest.mark.parametrize("case", ALIASES_PRINT_CASES) def test_aliases_print(case): cmd, match = case out, err, ret = run_xonsh(cmd=cmd, single_command=False) - assert re.match(match, out, re.MULTILINE | re.DOTALL), f"\nFailed:\n```\n{cmd.strip()}\n```,\nresult: {out!r}\nexpected: {match!r}." + assert re.match( + match, out, re.MULTILINE | re.DOTALL + ), f"\nFailed:\n```\n{cmd.strip()}\n```,\nresult: {out!r}\nexpected: {match!r}." @skip_if_on_windows diff --git a/xonsh/tools.py b/xonsh/tools.py index 764b8d0fe5..d65950e3ce 100644 --- a/xonsh/tools.py +++ b/xonsh/tools.py @@ -1129,6 +1129,7 @@ def display_colored_error_message(exc_info, strip_xonsh_error_types=True, limit= return import pygments.lexers.python + lexer = pygments.lexers.python.PythonTracebackLexer() tokens = list(pygments.lex(traceback_str, lexer=lexer)) # this goes to stdout, but since we are interactive it doesn't matter From 79fc0210f51bfb9287e71461c30c63e1655af9d7 Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Wed, 8 May 2024 00:28:47 +0200 Subject: [PATCH 27/39] test --- tests/test_integrations.py | 36 ++++++++++++++++++++++++++++++++++++ tests/test_tools.py | 6 +++--- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/tests/test_integrations.py b/tests/test_integrations.py index 6536d1bcf4..ebdbd81bab 100644 --- a/tests/test_integrations.py +++ b/tests/test_integrations.py @@ -1037,6 +1037,42 @@ def test_run_fail_not_on_path(): """, "f1f1f1\n.*\nTraceback.*\nZeroDivisionError: .*\nException in FuncAlias(.*)\nf2f2f2\n$" ), + ( +""" +$RAISE_SUBPROC_ERROR = False +$XONSH_SHOW_TRACEBACK = False +aliases['f'] = lambda: (None, "I failed", 2) +echo f1f1f1 ; f ; echo f2f2f2 +""", +"^f1f1f1\nI failed\nf2f2f2\n$" + ), + ( +""" +$RAISE_SUBPROC_ERROR = True +$XONSH_SHOW_TRACEBACK = False +aliases['f'] = lambda: (None, "I failed", 2) +echo f1f1f1 ; f ; echo f2f2f2 +""", +"f1f1f1\nI failed\nsubprocess.CalledProcessError.*\n$" + ), + ( +""" +$RAISE_SUBPROC_ERROR = True +$XONSH_SHOW_TRACEBACK = True +aliases['f'] = lambda: (None, "I failed", 2) +echo f1f1f1 ; f ; echo f2f2f2 +""", +"f1f1f1\nI failed.*\nTraceback.*\nsubprocess.CalledProcessError.*\n$" + ), + ( +""" +$RAISE_SUBPROC_ERROR = False +$XONSH_SHOW_TRACEBACK = True +aliases['f'] = lambda: (None, "I failed", 2) +echo f1f1f1 ; f ; echo f2f2f2 +""", +"f1f1f1\nI failed\nf2f2f2\n$" + ), ] @pytest.mark.parametrize("case", ALIASES_PRINT_CASES) diff --git a/tests/test_tools.py b/tests/test_tools.py index 56e9baeaea..eee08cd656 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -2122,7 +2122,7 @@ def test_print_exception_error(xession, capsys): match, cap.err, re.MULTILINE | re.DOTALL, - ), f"Assert: {cap.err!r} not matched with {match!r}" + ), f"\nAssert: {cap.err!r},\nexpected: {match!r}" with xession.env.swap(XONSH_SHOW_TRACEBACK=True): try: @@ -2130,9 +2130,9 @@ def test_print_exception_error(xession, capsys): except subprocess.CalledProcessError: print_exception(msg="MSG") cap = capsys.readouterr() - match = ".*Traceback.*subprocess.CalledProcessError: Command .* returned non-zero exit status .*\nMSG\n" + match = ".*Traceback.*subprocess.CalledProcessError: Command .* returned non-zero exit status .*MSG\n" assert re.match( match, cap.err, re.MULTILINE | re.DOTALL, - ), f"Assert: {cap.err!r} not matched with {match!r}" + ), f"\nAssert: {cap.err!r},\nexpected {match!r}" From b77dbf27bc07557eba31bd5bf3552f239ddc587b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 22:31:37 +0000 Subject: [PATCH 28/39] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_integrations.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/test_integrations.py b/tests/test_integrations.py index 3867fe9236..e0b490ba21 100644 --- a/tests/test_integrations.py +++ b/tests/test_integrations.py @@ -1038,43 +1038,44 @@ def test_run_fail_not_on_path(): "f1f1f1\n.*\nTraceback.*\nZeroDivisionError: .*\nException in FuncAlias(.*)\nf2f2f2\n$", ), ( -""" + """ $RAISE_SUBPROC_ERROR = False $XONSH_SHOW_TRACEBACK = False aliases['f'] = lambda: (None, "I failed", 2) echo f1f1f1 ; f ; echo f2f2f2 """, -"^f1f1f1\nI failed\nf2f2f2\n$" + "^f1f1f1\nI failed\nf2f2f2\n$", ), ( -""" + """ $RAISE_SUBPROC_ERROR = True $XONSH_SHOW_TRACEBACK = False aliases['f'] = lambda: (None, "I failed", 2) echo f1f1f1 ; f ; echo f2f2f2 """, -"f1f1f1\nI failed\nsubprocess.CalledProcessError.*\n$" + "f1f1f1\nI failed\nsubprocess.CalledProcessError.*\n$", ), ( -""" + """ $RAISE_SUBPROC_ERROR = True $XONSH_SHOW_TRACEBACK = True aliases['f'] = lambda: (None, "I failed", 2) echo f1f1f1 ; f ; echo f2f2f2 """, -"f1f1f1\nI failed.*\nTraceback.*\nsubprocess.CalledProcessError.*\n$" + "f1f1f1\nI failed.*\nTraceback.*\nsubprocess.CalledProcessError.*\n$", ), ( -""" + """ $RAISE_SUBPROC_ERROR = False $XONSH_SHOW_TRACEBACK = True aliases['f'] = lambda: (None, "I failed", 2) echo f1f1f1 ; f ; echo f2f2f2 """, -"f1f1f1\nI failed\nf2f2f2\n$" + "f1f1f1\nI failed\nf2f2f2\n$", ), ] + @pytest.mark.parametrize("case", ALIASES_PRINT_CASES) def test_aliases_print(case): cmd, match = case From 1609d019a170a135b65742f81d6bd728484a9fdf Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Wed, 8 May 2024 00:41:28 +0200 Subject: [PATCH 29/39] test --- news/{aliases_imp.rst => funcalias.rst} | 0 tests/test_integrations.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename news/{aliases_imp.rst => funcalias.rst} (100%) diff --git a/news/aliases_imp.rst b/news/funcalias.rst similarity index 100% rename from news/aliases_imp.rst rename to news/funcalias.rst diff --git a/tests/test_integrations.py b/tests/test_integrations.py index e0b490ba21..ab1eb2d290 100644 --- a/tests/test_integrations.py +++ b/tests/test_integrations.py @@ -1075,7 +1075,7 @@ def test_run_fail_not_on_path(): ), ] - +@skip_if_on_windows @pytest.mark.parametrize("case", ALIASES_PRINT_CASES) def test_aliases_print(case): cmd, match = case From a8d7ff8eb9262bbf8caecae6082aa4b63cd9eb3e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 22:41:44 +0000 Subject: [PATCH 30/39] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_integrations.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_integrations.py b/tests/test_integrations.py index ab1eb2d290..714e3b563d 100644 --- a/tests/test_integrations.py +++ b/tests/test_integrations.py @@ -1075,6 +1075,7 @@ def test_run_fail_not_on_path(): ), ] + @skip_if_on_windows @pytest.mark.parametrize("case", ALIASES_PRINT_CASES) def test_aliases_print(case): From 8b5b76a3d78bc9d2d221617e610adad8eafa7f45 Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Wed, 8 May 2024 00:45:02 +0200 Subject: [PATCH 31/39] news --- news/funcalias.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/news/funcalias.rst b/news/funcalias.rst index c694bbefcd..895388b78b 100644 --- a/news/funcalias.rst +++ b/news/funcalias.rst @@ -1,6 +1,7 @@ **Added:** * Added FuncAlias to process callable aliases. +* Added alias name printing in case of exception in alias. **Changed:** @@ -16,7 +17,7 @@ **Fixed:** -* +* Fixed showing alias description using superhelp e.g. ``which?``. **Security:** From 235917cd5546c3344468870ea11108aa95040106 Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Sat, 11 May 2024 11:38:11 +0200 Subject: [PATCH 32/39] wip --- xonsh/aliases.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xonsh/aliases.py b/xonsh/aliases.py index 20705825f0..162a31457e 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -69,7 +69,7 @@ def __init__(self, name, func): self.__setattr__(attr, val) def __repr__(self): - r = {"name": self.name, "func": self.func} + r = {"name": self.name, "func": self.func.__name__} r |= { attr: val for attr in self.attributes_show From c3d84e9357a4cf1b0bf54fa6880b7870dffe9d1c Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Sat, 11 May 2024 11:56:31 +0200 Subject: [PATCH 33/39] wip --- xonsh/aliases.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/xonsh/aliases.py b/xonsh/aliases.py index 162a31457e..5f71d2112d 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -80,16 +80,10 @@ def __repr__(self): def __call__( self, args=None, stdin=None, stdout=None, stderr=None, spec=None, stack=None ): - try: - func_args = [args, stdin, stdout, stderr, spec, stack][ - : len(inspect.signature(self.func).parameters) - ] - return self.func(*func_args) - except Exception: - if XSH.env.get("RAISE_SUBPROC_ERROR", True): - raise - else: - print_exception(f"Exception in {repr(self)}") + func_args = [args, stdin, stdout, stderr, spec, stack][ + : len(inspect.signature(self.func).parameters) + ] + return self.func(*func_args) class Aliases(cabc.MutableMapping): From f00c121cf3cb876e7dddb2bae32b27c3a551c049 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 11 May 2024 09:56:46 +0000 Subject: [PATCH 34/39] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xonsh/aliases.py | 1 - 1 file changed, 1 deletion(-) diff --git a/xonsh/aliases.py b/xonsh/aliases.py index 5f71d2112d..b1b3961aa9 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -40,7 +40,6 @@ argvquote, escape_windows_cmd_string, print_color, - print_exception, strip_simple_quotes, swap_values, to_repr_pretty_, From 5790d54fc901d0c47d01c38b98894ed7c1aac714 Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Sat, 11 May 2024 11:58:24 +0200 Subject: [PATCH 35/39] wip --- xonsh/aliases.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xonsh/aliases.py b/xonsh/aliases.py index 5f71d2112d..05aa0ff01f 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -58,8 +58,9 @@ def EXEC_ALIAS_RE(): class FuncAlias: """Provides a callable alias for xonsh commands.""" - attributes_inherit = ["__xonsh_threadable__", "__xonsh_capturable__", "__doc__"] attributes_show = ["__xonsh_threadable__", "__xonsh_capturable__"] + attributes_inherit = attributes_show + ["__doc__"] + def __init__(self, name, func): self.__name__ = self.name = name From a1726c78e54a81ebcf0ec878417aca603f383e5f Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Sat, 11 May 2024 12:03:20 +0200 Subject: [PATCH 36/39] Fix tests --- tests/test_integrations.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_integrations.py b/tests/test_integrations.py index 714e3b563d..09b3a29501 100644 --- a/tests/test_integrations.py +++ b/tests/test_integrations.py @@ -1008,7 +1008,7 @@ def test_run_fail_not_on_path(): aliases['f'] = lambda: 1/0 echo f1f1f1 ; f ; echo f2f2f2 """, - "^f1f1f1\nZeroDivisionError: .*\nException in FuncAlias(.*)\nf2f2f2\n$", + "^f1f1f1\nException in thread.*FuncAlias.*\nZeroDivisionError.*\nf2f2f2\n$", ), ( """ @@ -1035,7 +1035,7 @@ def test_run_fail_not_on_path(): aliases['f'] = lambda: 1/0 echo f1f1f1 ; f ; echo f2f2f2 """, - "f1f1f1\n.*\nTraceback.*\nZeroDivisionError: .*\nException in FuncAlias(.*)\nf2f2f2\n$", + "f1f1f1\nException in thread.*FuncAlias.*\nTraceback.*\nZeroDivisionError.*\nf2f2f2\n$", ), ( """ From c7dc5c0ed9bb6f21e7217751f113df1b185f41b9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 11 May 2024 10:03:42 +0000 Subject: [PATCH 37/39] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xonsh/aliases.py | 1 - 1 file changed, 1 deletion(-) diff --git a/xonsh/aliases.py b/xonsh/aliases.py index 999de120df..1ebdf31ae4 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -60,7 +60,6 @@ class FuncAlias: attributes_show = ["__xonsh_threadable__", "__xonsh_capturable__"] attributes_inherit = attributes_show + ["__doc__"] - def __init__(self, name, func): self.__name__ = self.name = name self.func = func From 73afcbe7a225b9e963decfa5fa2763e251d99bf1 Mon Sep 17 00:00:00 2001 From: a <1@1.1> Date: Sat, 11 May 2024 12:16:34 +0200 Subject: [PATCH 38/39] Fix tests --- tests/test_integrations.py | 86 +++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/tests/test_integrations.py b/tests/test_integrations.py index 09b3a29501..91058a61e3 100644 --- a/tests/test_integrations.py +++ b/tests/test_integrations.py @@ -1000,7 +1000,7 @@ def test_run_fail_not_on_path(): assert out != "Hello world" -ALIASES_PRINT_CASES = [ +ALIASES_THREADABLE_PRINT_CASES = [ ( """ $RAISE_SUBPROC_ERROR = False @@ -1075,9 +1075,91 @@ def test_run_fail_not_on_path(): ), ] +ALIASES_UNTHREADABLE_PRINT_CASES = [ + ( + """ +$RAISE_SUBPROC_ERROR = False +$XONSH_SHOW_TRACEBACK = False +aliases['f'] = lambda: 1/0 +aliases['f'].__xonsh_threadable__ = False +echo f1f1f1 ; f ; echo f2f2f2 +""", + "^f1f1f1\nException in.*FuncAlias.*\nZeroDivisionError.*\nf2f2f2\n$", + ), + ( + """ +$RAISE_SUBPROC_ERROR = True +$XONSH_SHOW_TRACEBACK = False +aliases['f'] = lambda: 1/0 +aliases['f'].__xonsh_threadable__ = False +echo f1f1f1 ; f ; echo f2f2f2 +""", + "f1f1f1\nException in.*\nZeroDivisionError: .*\nsubprocess.CalledProcessError.*\n$", + ), + ( + """ +$RAISE_SUBPROC_ERROR = True +$XONSH_SHOW_TRACEBACK = True +aliases['f'] = lambda: 1/0 +aliases['f'].__xonsh_threadable__ = False +echo f1f1f1 ; f ; echo f2f2f2 +""", + "f1f1f1\nException in.*\nTraceback.*\nZeroDivisionError: .*\nsubprocess.CalledProcessError.*\n$", + ), + ( + """ +$RAISE_SUBPROC_ERROR = False +$XONSH_SHOW_TRACEBACK = True +aliases['f'] = lambda: 1/0 +aliases['f'].__xonsh_threadable__ = False +echo f1f1f1 ; f ; echo f2f2f2 +""", + "f1f1f1\nException in.*FuncAlias.*\nTraceback.*\nZeroDivisionError.*\nf2f2f2\n$", + ), + ( + """ +$RAISE_SUBPROC_ERROR = False +$XONSH_SHOW_TRACEBACK = False +aliases['f'] = lambda: (None, "I failed", 2) +aliases['f'].__xonsh_threadable__ = False +echo f1f1f1 ; f ; echo f2f2f2 +""", + "^f1f1f1\nI failed\nf2f2f2\n$", + ), + ( + """ +$RAISE_SUBPROC_ERROR = True +$XONSH_SHOW_TRACEBACK = False +aliases['f'] = lambda: (None, "I failed", 2) +aliases['f'].__xonsh_threadable__ = False +echo f1f1f1 ; f ; echo f2f2f2 +""", + "f1f1f1\nI failed\nsubprocess.CalledProcessError.*\n$", + ), + ( + """ +$RAISE_SUBPROC_ERROR = True +$XONSH_SHOW_TRACEBACK = True +aliases['f'] = lambda: (None, "I failed", 2) +aliases['f'].__xonsh_threadable__ = False +echo f1f1f1 ; f ; echo f2f2f2 +""", + "f1f1f1\nI failed.*\nTraceback.*\nsubprocess.CalledProcessError.*\n$", + ), + ( + """ +$RAISE_SUBPROC_ERROR = False +$XONSH_SHOW_TRACEBACK = True +aliases['f'] = lambda: (None, "I failed", 2) +aliases['f'].__xonsh_threadable__ = False +echo f1f1f1 ; f ; echo f2f2f2 +""", + "f1f1f1\nI failed\nf2f2f2\n$", + ), +] @skip_if_on_windows -@pytest.mark.parametrize("case", ALIASES_PRINT_CASES) +@pytest.mark.parametrize("case", ALIASES_THREADABLE_PRINT_CASES + ALIASES_UNTHREADABLE_PRINT_CASES) def test_aliases_print(case): cmd, match = case out, err, ret = run_xonsh(cmd=cmd, single_command=False) From 7a26c12ddbc07ca9e2ad0ce43e716160c4cc6dae Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 11 May 2024 10:16:53 +0000 Subject: [PATCH 39/39] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_integrations.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/test_integrations.py b/tests/test_integrations.py index 91058a61e3..3e2c448620 100644 --- a/tests/test_integrations.py +++ b/tests/test_integrations.py @@ -1158,8 +1158,11 @@ def test_run_fail_not_on_path(): ), ] + @skip_if_on_windows -@pytest.mark.parametrize("case", ALIASES_THREADABLE_PRINT_CASES + ALIASES_UNTHREADABLE_PRINT_CASES) +@pytest.mark.parametrize( + "case", ALIASES_THREADABLE_PRINT_CASES + ALIASES_UNTHREADABLE_PRINT_CASES +) def test_aliases_print(case): cmd, match = case out, err, ret = run_xonsh(cmd=cmd, single_command=False)