Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added FuncAlias #5366

Merged
merged 54 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
5fb6485
FuncAlias
Apr 25, 2024
2dcc6f9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 25, 2024
12322eb
FuncAlias
Apr 25, 2024
6c9ceca
Merge remote-tracking branch 'origin/main' into func_alias
Apr 27, 2024
d7a4af7
wip
Apr 27, 2024
0ddbca0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 27, 2024
8f58a2f
wip
Apr 27, 2024
6893614
update
Apr 27, 2024
daf7f18
wip
Apr 27, 2024
49732d3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 27, 2024
87b59f9
wip
Apr 27, 2024
a95de7f
update
Apr 27, 2024
226ef6f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 27, 2024
ee3dad5
Merge remote-tracking branch 'origin/main' into func_alias
Apr 29, 2024
bf12f62
inherit __doc__
Apr 29, 2024
330fa12
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 29, 2024
ea5014d
Merge remote-tracking branch 'origin/main' into func_alias
May 2, 2024
d13b5a8
Merge remote-tracking branch 'origin/main' into func_alias
May 2, 2024
898d24a
Merge remote-tracking branch 'origin/main' into func_alias
May 3, 2024
61172fd
Merge remote-tracking branch 'origin/main' into func_alias
May 4, 2024
096abdb
Merge remote-tracking branch 'origin/main' into func_alias
May 6, 2024
aa4cd8c
wip
May 6, 2024
67f3bfa
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 6, 2024
6154480
wip
May 6, 2024
7a526f6
Merge remote-tracking branch 'origin/func_alias' into func_alias
May 6, 2024
312ed42
update
May 6, 2024
8cf9762
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 6, 2024
a9e0595
[pre-commit.ci] pre-commit autoupdate (#5397)
pre-commit-ci[bot] May 6, 2024
4eef469
update
May 6, 2024
51c5c37
update
May 7, 2024
75bc389
removed partial_proxy
May 7, 2024
c77ff66
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 7, 2024
9f8b7cd
test
May 7, 2024
c35cd32
Merge remote-tracking branch 'origin/func_alias' into func_alias
May 7, 2024
1fbca90
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 7, 2024
79fc021
test
May 7, 2024
dd21ec8
Merge remote-tracking branch 'origin/func_alias' into func_alias
May 7, 2024
b77dbf2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 7, 2024
4b490b0
Merge remote-tracking branch 'origin/main' into func_alias
May 7, 2024
1609d01
test
May 7, 2024
a8d7ff8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 7, 2024
8b5b76a
news
May 7, 2024
1b5c30b
Merge remote-tracking branch 'origin/func_alias' into func_alias
May 7, 2024
09e7d36
Merge remote-tracking branch 'origin/main' into func_alias
May 10, 2024
235917c
wip
May 11, 2024
c3d84e9
wip
May 11, 2024
f00c121
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 11, 2024
5790d54
wip
May 11, 2024
a1726c7
Fix tests
May 11, 2024
00a2ccc
Merge remote-tracking branch 'origin/func_alias' into func_alias
May 11, 2024
c7dc5c0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 11, 2024
73afcbe
Fix tests
May 11, 2024
847317f
Merge remote-tracking branch 'origin/func_alias' into func_alias
May 11, 2024
7a26c12
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 24 additions & 0 deletions news/funcalias.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
**Added:**

* Added FuncAlias to process callable aliases.
* Added alias name printing in case of exception in alias.

**Changed:**

* <news item>

**Deprecated:**

* <news item>

**Removed:**

* <news item>

**Fixed:**

* Fixed showing alias description using superhelp e.g. ``which?``.

**Security:**

* <news item>
5 changes: 3 additions & 2 deletions tests/test_aliases.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from xonsh.aliases import Aliases, ExecAlias


def cd(args, stdin=None, **kwargs):
def cd(args, stdin=None):
return args


Expand All @@ -30,10 +30,11 @@ def test_imports(xession):
"o": ["omg", "lala"],
"ls": ["ls", "- -"],
"color_ls": ["ls", "--color=true"],
"cd": cd,
"cd": "FuncAlias",
"indirect_cd": ["cd", ".."],
}
raw = ales._raw
raw["cd"] = type(ales["cd"]).__name__
assert raw == expected


Expand Down
171 changes: 171 additions & 0 deletions tests/test_integrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,177 @@ def test_run_fail_not_on_path():
assert out != "Hello world"


ALIASES_THREADABLE_PRINT_CASES = [
(
"""
$RAISE_SUBPROC_ERROR = False
$XONSH_SHOW_TRACEBACK = False
aliases['f'] = lambda: 1/0
echo f1f1f1 ; f ; echo f2f2f2
""",
"^f1f1f1\nException in thread.*FuncAlias.*\nZeroDivisionError.*\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\nException in thread.*FuncAlias.*\nTraceback.*\nZeroDivisionError.*\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$",
),
]

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_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)
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):
Expand Down
6 changes: 3 additions & 3 deletions tests/test_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -2122,17 +2122,17 @@ 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:
raise subprocess.CalledProcessError(1, ["ls", "nofile"], output="nooutput")
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}"
35 changes: 34 additions & 1 deletion xonsh/aliases.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,37 @@ def EXEC_ALIAS_RE():
return re.compile(r"@\(|\$\(|!\(|\$\[|!\[|\&\&|\|\||\s+and\s+|\s+or\s+|[>|<]")


class FuncAlias:
"""Provides a callable alias for xonsh commands."""

attributes_show = ["__xonsh_threadable__", "__xonsh_capturable__"]
attributes_inherit = attributes_show + ["__doc__"]

def __init__(self, name, func):
self.__name__ = self.name = name
self.func = func
for attr in self.attributes_inherit:
if (val := getattr(func, attr, None)) is not None:
self.__setattr__(attr, val)

def __repr__(self):
r = {"name": self.name, "func": self.func.__name__}
r |= {
attr: val
for attr in self.attributes_show
if (val := getattr(self, attr, None)) is not None
}
return f"FuncAlias({repr(r)})"

def __call__(
self, args=None, stdin=None, stdout=None, stderr=None, spec=None, stack=None
):
func_args = [args, stdin, stdout, stderr, spec, stack][
: len(inspect.signature(self.func).parameters)
]
return self.func(*func_args)


class Aliases(cabc.MutableMapping):
"""Represents a location to hold and look up aliases."""

Expand Down Expand Up @@ -182,6 +213,8 @@ def __setitem__(self, key, val):
else:
# need to exec alias
self._raw[key] = ExecAlias(val, filename=f)
elif isinstance(val, types.FunctionType):
self._raw[key] = FuncAlias(key, val)
else:
self._raw[key] = val

Expand Down Expand Up @@ -225,7 +258,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="<exec-alias>"):
"""
Expand Down