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

Fix parsing of redirect tokens #5322

Merged
merged 5 commits into from
Apr 5, 2024

Conversation

yaxollum
Copy link
Member

@yaxollum yaxollum commented Apr 4, 2024

Fixes #2335

This fix changes the parser so that a command like echo test > a.txt < b.txt o>e is passed like ['echo', 'test', ('>', 'a.txt'), ('<', 'b.txt'), ('o>e',)] to cmds_to_specs.

Currently, the command is passed like ['echo', 'test', '>', 'a.txt', '<', 'b.txt', 'o>e'], which is what causes the ambiguity between a > redirect token and a ">" string literal.

For community

⬇️ Please click the 👍 reaction instead of leaving a +1 or 👍 comment

In the parser, wrap redirect tokens such as ">", "a>", and "2>1" in a
tuple (along with the name of the redirect file, if applicable) to
differentiate them from regular command line arguments.

This ensures that a command like ![echo ">"] is parsed correctly.

We now need 2 types of IO-redirect tokens (IOREDIRECT1 and IOREDIRECT2)
so that the parser knows whether or not an IO-redirect has a file
argument. For example, "a>" has type IOREDIRECT1, whereas "2>1" has
type IOREDIRECT2.
@codecov-commenter
Copy link

codecov-commenter commented Apr 4, 2024

Codecov Report

Attention: Patch coverage is 87.50000% with 4 lines in your changes are missing coverage. Please review.

Project coverage is 67.37%. Comparing base (7c23508) to head (5d6c271).
Report is 28 commits behind head on main.

Files Patch % Lines
xonsh/procs/specs.py 71.42% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5322      +/-   ##
==========================================
+ Coverage   67.14%   67.37%   +0.22%     
==========================================
  Files         119      119              
  Lines       23125    23137      +12     
  Branches     4855     4860       +5     
==========================================
+ Hits        15528    15588      +60     
+ Misses       6391     6330      -61     
- Partials     1206     1219      +13     
Flag Coverage Δ
macOS-latest 64.66% <87.50%> (+0.17%) ⬆️
ubuntu-latest 64.96% <87.50%> (+0.24%) ⬆️
windows-latest 63.33% <87.50%> (+0.27%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@jnoortheen jnoortheen merged commit 08ac0d9 into xonsh:main Apr 5, 2024
15 checks passed
@jnoortheen
Copy link
Member

LGTM, Thanks @yaxollum !

@jnoortheen
Copy link
Member

Hi @yaxollum , I think the following error happens because of the change . I am posting the full traceback with rich tracebacks

❯ git-cola 2> /dev/null &
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /Users/noor/.virtualenvs/xonfig-NTkDZBCY-py3.12/lib/python3.12/site-packages/xonsh/base_shell.py │
│ :392 in default                                                                                  │
│                                                                                                  │
│   389 │   │   try:                                                                               │
│   390 │   │   │   exc_info = run_compiled_code(code, self.ctx, None, "single")                   │
│   391 │   │   │   if exc_info != (None, None, None):                                             │
│ ❱ 392 │   │   │   │   raise exc_info[1]                                                          │
│   393 │   │   │   ts1 = time.time()                                                              │
│   394 │   │   │   if hist is not None and hist.last_cmd_rtn is None:                             │
│   395 │   │   │   │   hist.last_cmd_rtn = 0  # returncode for success                            │
│                                                                                                  │
│ ╭───────────────────────────────────── locals ─────────────────────────────────────╮             │
│ │     code = <code object <module> at 0x10b683b90, file "<stdin>", line 1>         │             │
│ │      enc = 'utf-8'                                                               │             │
│ │      env = xonsh.environ.Env(...)                                                │             │
│ │      err = 'surrogateescape'                                                     │             │
│ │ exc_info = (                                                                     │             │
│ │            │   <class 'TypeError'>,                                              │             │
│ │            │   TypeError('sequence item 1: expected str instance, tuple found'), │             │
│ │            │   <traceback object at 0x10b44f600>                                 │             │
│ │            )                                                                     │             │
│ │     hist = <xonsh.history.sqlite.SqliteHistory object at 0x10b370980>            │             │
│ │     line = 'git-cola 2> /dev/null &\n'                                           │             │
│ │ raw_line = 'git-cola 2> /dev/null &'                                             │             │
│ │     self = <xonsh.ptk_shell.shell.PromptToolkitShell object at 0x10b371850>      │             │
│ │      src = 'git-cola 2> /dev/null &\n'                                           │             │
│ │      tee = <xonsh.base_shell.Tee object at 0x107ce9c40>                          │             │
│ │      ts0 = 1712666211.1072829                                                    │             │
│ │      ts1 = None                                                                  │             │
│ ╰──────────────────────────────────────────────────────────────────────────────────╯             │
│                                                                                                  │
│ /Users/noor/.virtualenvs/xonfig-NTkDZBCY-py3.12/lib/python3.12/site-packages/xonsh/codecache.py: │
│ 64 in run_compiled_code                                                                          │
│                                                                                                  │
│    61 │   else:                                                                                  │
│    62 │   │   func = eval                                                                        │
│    63 │   try:                                                                                   │
│ ❱  64 │   │   func(code, glb, loc)                                                               │
│    65 │   │   return (None, None, None)                                                          │
│    66 │   except BaseException:                                                                  │
│    67 │   │   type, value, traceback = sys.exc_info()                                            │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │      code = <code object <module> at 0x10b683b90, file "<stdin>", line 1>                    │ │
│ │      func = <built-in function exec>                                                         │ │
│ │       glb = {                                                                                │ │
│ │             │   '__builtins__': {                                                            │ │
│ │             │   │   '__name__': 'builtins',                                                  │ │
│ │             │   │   '__doc__': 'Built-in functions, types, exceptions, and other             │ │
│ │             objects.\n\nThis module provides '+346,                                          │ │
│ │             │   │   '__package__': '',                                                       │ │
│ │             │   │   '__loader__': <class '_frozen_importlib.BuiltinImporter'>,               │ │
│ │             │   │   '__spec__': ModuleSpec(name='builtins', loader=<class                    │ │
│ │             '_frozen_importlib.BuiltinImporter'>, origin='built-in'),                        │ │
│ │             │   │   '__build_class__': <built-in function __build_class__>,                  │ │
│ │             │   │   '__import__': <built-in function __import__>,                            │ │
│ │             │   │   'abs': <built-in function abs>,                                          │ │
│ │             │   │   'all': <built-in function all>,                                          │ │
│ │             │   │   'any': <built-in function any>,                                          │ │
│ │             │   │   ... +158                                                                 │ │
│ │             │   },                                                                           │ │
│ │             │   'io': <module 'io' (frozen)>,                                                │ │
│ │             │   'sys': <module 'sys' (built-in)>,                                            │ │
│ │             │   '_init_conda_env': <function _init_conda_env at 0x106fda020>,                │ │
│ │             │   'abbrevs': {                                                                 │ │
│ │             │   │   '_get_branches': <function _get_branches at 0x10b33a8e0>,                │ │
│ │             │   │   '_get_dev_branch': <function _get_dev_branch at 0x10b31d940>,            │ │
│ │             │   │   '_get_main_branch': <function _get_main_branch at 0x10b31df80>,          │ │
│ │             │   │   '_git_checkout': <function _git_checkout at 0x10b31e020>,                │ │
│ │             │   │   '_git_checkout_merge': <function _git_checkout_merge at 0x10b31e0c0>,    │ │
│ │             │   │   'gl': 'git log --oneline --all --graph',                                 │ │
│ │             │   │   'gf': 'git fetch --all --prune --tags',                                  │ │
│ │             │   │   'gp': 'git push --follow-tags',                                          │ │
│ │             │   │   'gpl': 'git pull',                                                       │ │
│ │             │   │   'gcd': <function _git_checkout.<locals>._wrapper at 0x10b31e160>,        │ │
│ │             │   │   ... +26                                                                  │ │
│ │             │   },                                                                           │ │
│ │             │   'LONG_DURATION': 5,                                                          │ │
│ │             │   'NOTIFICATION_APP_NAME': '{current_job:{} | }{user}@{hostname}: {cwd} |      │ │
│ │             xonsh',                                                                          │ │
│ │             │   'TRIGGER_NOTIFICATION': True,                                                │ │
│ │             │   'functools': <module 'functools' from                                        │ │
│ │             '/opt/homebrew/Cellar/python@3.12/3.12.2_1/Frameworks/Python.framework/Versions… │ │
│ │             │   'is_app_window_focused': <function is_app_window_focused at 0x10b339940>,    │ │
│ │             │   ... +74                                                                      │ │
│ │             }                                                                                │ │
│ │       loc = None                                                                             │ │
│ │      mode = 'single'                                                                         │ │
│ │ traceback = <traceback object at 0x10b44f600>                                                │ │
│ │      type = <class 'TypeError'>                                                              │ │
│ │     value = TypeError('sequence item 1: expected str instance, tuple found')                 │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ in <module>:1                                                                                    │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │            _init_conda_env = <function _init_conda_env at 0x106fda020>                       │ │
│ │                    abbrevs = {                                                               │ │
│ │                              │   '_get_branches': <function _get_branches at 0x10b33a8e0>,   │ │
│ │                              │   '_get_dev_branch': <function _get_dev_branch at             │ │
│ │                              0x10b31d940>,                                                   │ │
│ │                              │   '_get_main_branch': <function _get_main_branch at           │ │
│ │                              0x10b31df80>,                                                   │ │
│ │                              │   '_git_checkout': <function _git_checkout at 0x10b31e020>,   │ │
│ │                              │   '_git_checkout_merge': <function _git_checkout_merge at     │ │
│ │                              0x10b31e0c0>,                                                   │ │
│ │                              │   'gl': 'git log --oneline --all --graph',                    │ │
│ │                              │   'gf': 'git fetch --all --prune --tags',                     │ │
│ │                              │   'gp': 'git push --follow-tags',                             │ │
│ │                              │   'gpl': 'git pull',                                          │ │
│ │                              │   'gcd': <function _git_checkout.<locals>._wrapper at         │ │
│ │                              0x10b31e160>,                                                   │ │
│ │                              │   ... +26                                                     │ │
│ │                              }                                                               │ │
│ │                        add = <pipe.Pipe object at 0x107ba6cf0>                               │ │
│ │                  aggregate = <pipe.Pipe object at 0x107ba6e70>                               │ │
│ │                        all = <pipe.Pipe object at 0x107ba6840>                               │ │
│ │                        any = <pipe.Pipe object at 0x107ba6870>                               │ │
│ │                    as_dict = <pipe.Pipe object at 0x107ba69c0>                               │ │
│ │                    as_list = <pipe.Pipe object at 0x107ba6b70>                               │ │
│ │                     as_set = <pipe.Pipe object at 0x107ba69f0>                               │ │
│ │                   as_tuple = <pipe.Pipe object at 0x107ba6ba0>                               │ │
│ │                    average = <pipe.Pipe object at 0x107ba68d0>                               │ │
│ │                      chain = <pipe.Pipe object at 0x107ba71d0>                               │ │
│ │                 chain_with = <pipe.Pipe object at 0x107ba7230>                               │ │
│ │             CommandContext = <class 'xonsh.parsers.completion_context.CommandContext'>       │ │
│ │                  completer = <module 'xonsh.completers.completer' from                       │ │
│ │                              '/Users/noor/.virtualenvs/xonfig-NTkDZBCY-py3.12/lib/python3.1… │ │
│ │                     concat = <pipe.Pipe object at 0x107ba6b40>                               │ │
│ │             contextmanager = <function contextmanager at 0x104fc23e0>                        │ │
│ │                      count = <pipe.Pipe object at 0x107ba6900>                               │ │
│ │         custom_keybindings = <function custom_keybindings at 0x10b339d00>                    │ │
│ │                      dedup = <pipe.Pipe object at 0x107ba67e0>                               │ │
│ │ django_manage_py_completer = <function django_manage_py_completer at 0x10b31d620>            │ │
│ │                      first = <pipe.Pipe object at 0x107ba6d80>                               │ │
│ │                  functools = <module 'functools' from                                        │ │
│ │                              '/opt/homebrew/Cellar/python@3.12/3.12.2_1/Frameworks/Python.f… │ │
│ │                    groupby = <pipe.Pipe object at 0x107ba6ed0>                               │ │
│ │                      index = <pipe.Pipe object at 0x107ba6fc0>                               │ │
│ │                         io = <module 'io' (frozen)>                                          │ │
│ │      is_app_window_focused = <function is_app_window_focused at 0x10b339940>                 │ │
│ │           is_darwin_system = <functools._lru_cache_wrapper object at 0x1071c64b0>            │ │
│ │            is_linux_system = <functools._lru_cache_wrapper object at 0x1071c6400>            │ │
│ │                  is_system = <function is_system at 0x10b339440>                             │ │
│ │                     islice = <pipe.Pipe object at 0x107ba7260>                               │ │
│ │                       izip = <pipe.Pipe object at 0x107ba7290>                               │ │
│ │                    lineout = <pipe.Pipe object at 0x107ba6c00>                               │ │
│ │          long_cmd_duration = <function long_cmd_duration at 0x10b339a80>                     │ │
│ │              LONG_DURATION = 5                                                               │ │
│ │                     lstrip = <pipe.Pipe object at 0x107ba70b0>                               │ │
│ │                       main = <function main at 0x10b33a660>                                  │ │
│ │                        map = <pipe.Pipe object at 0x107ba6db0>                               │ │
│ │                        max = <pipe.Pipe object at 0x107ba6960>                               │ │
│ │                        min = <pipe.Pipe object at 0x107ba6990>                               │ │
│ │               mk_temp_file = <function mk_temp_file at 0x10b339bc0>                          │ │
│ │                     netcat = <pipe.Pipe object at 0x107ba6a80>                               │ │
│ │                   netwrite = <pipe.Pipe object at 0x107ba6ab0>                               │ │
│ │      NOTIFICATION_APP_NAME = '{current_job:{} | }{user}@{hostname}: {cwd} | xonsh'           │ │
│ │                notify_user = <function notify_user at 0x10b3399e0>                           │ │
│ │                         os = <module 'os' (frozen)>                                          │ │
│ │                     passed = <pipe.Pipe object at 0x107ba6f60>                               │ │
│ │               permutations = <pipe.Pipe object at 0x107ba6a20>                               │ │
│ │                       Pipe = <class 'pipe.Pipe'>                                             │ │
│ │                    reverse = <pipe.Pipe object at 0x107ba6f30>                               │ │
│ │                     rstrip = <pipe.Pipe object at 0x107ba7080>                               │ │
│ │                   run_with = <pipe.Pipe object at 0x107ba70e0>                               │ │
│ │           secs_to_readable = <function secs_to_readable at 0x10b3393a0>                      │ │
│ │                     select = <pipe.Pipe object at 0x107ba6db0>                               │ │
│ │                       skip = <pipe.Pipe object at 0x107ba6750>                               │ │
│ │                 skip_while = <pipe.Pipe object at 0x107ba6e40>                               │ │
│ │                       sort = <pipe.Pipe object at 0x107ba6f00>                               │ │
│ │                         sp = <module 'subprocess' from                                       │ │
│ │                              '/opt/homebrew/Cellar/python@3.12/3.12.2_1/Frameworks/Python.f… │ │
│ │                     stdout = <pipe.Pipe object at 0x107ba6bd0>                               │ │
│ │                      strip = <pipe.Pipe object at 0x107ba6ff0>                               │ │
│ │                 subprocess = <module 'subprocess' from                                       │ │
│ │                              '/opt/homebrew/Cellar/python@3.12/3.12.2_1/Frameworks/Python.f… │ │
│ │                        sys = <module 'sys' (built-in)>                                       │ │
│ │                          t = <pipe.Pipe object at 0x107ba7110>                               │ │
│ │                       tail = <pipe.Pipe object at 0x107ba55b0>                               │ │
│ │                       take = <pipe.Pipe object at 0x107ba5460>                               │ │
│ │                 take_while = <pipe.Pipe object at 0x107ba6e10>                               │ │
│ │                        tee = <pipe.Pipe object at 0x107ba6c30>                               │ │
│ │                   tempfile = <module 'tempfile' from                                         │ │
│ │                              '/opt/homebrew/Cellar/python@3.12/3.12.2_1/Frameworks/Python.f… │ │
│ │                    to_type = <pipe.Pipe object at 0x107ba7170>                               │ │
│ │                      tools = <module 'xonsh.completers.tools' from                           │ │
│ │                              '/Users/noor/.virtualenvs/xonfig-NTkDZBCY-py3.12/lib/python3.1… │ │
│ │                  transpose = <pipe.Pipe object at 0x107ba71a0>                               │ │
│ │                   traverse = <pipe.Pipe object at 0x107ba6b10>                               │ │
│ │       TRIGGER_NOTIFICATION = True                                                            │ │
│ │               uncapturable = <function uncapturable at 0x10546fc40>                          │ │
│ │                       uniq = <pipe.Pipe object at 0x107ba6810>                               │ │
│ │                      where = <pipe.Pipe object at 0x107ba6de0>                               │ │
│ │                          X = X                                                               │ │
│ │                        xpf = <module 'xontrib_powerline3.fields' from                        │ │
│ │                              '/Users/noor/src/shell/ig/exts/powerline/xontrib_powerline3/fi… │ │
│ │                        xpp = <module 'xontrib_powerline3.processor' from                     │ │
│ │                              '/Users/noor/src/shell/ig/exts/powerline/xontrib_powerline3/pr… │ │
│ │                        xsh = <xonsh.built_ins.XonshSession object at 0x105381790>            │ │
│ │                        XSH = <xonsh.built_ins.XonshSession object at 0x105381790>            │ │
│ │           XSH_DIRS_HISTORY = <Dirs: >                                                        │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /Users/noor/.virtualenvs/xonfig-NTkDZBCY-py3.12/lib/python3.12/site-packages/xonsh/built_ins.py: │
│ 206 in subproc_captured_hiddenobject                                                             │
│                                                                                                  │
│   203 │   """                                                                                    │
│   204 │   import xonsh.procs.specs                                                               │
│   205 │                                                                                          │
│ ❱ 206 │   return xonsh.procs.specs.run_subproc(cmds, captured="hiddenobject", envs=envs)         │
│   207                                                                                            │
│   208                                                                                            │
│   209 def subproc_uncaptured(*cmds, envs=None):                                                  │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │  cmds = (['git-cola', ('2>', '/dev/null')], '&')                                             │ │
│ │  envs = None                                                                                 │ │
│ │ xonsh = <module 'xonsh' from                                                                 │ │
│ │         '/Users/noor/.virtualenvs/xonfig-NTkDZBCY-py3.12/lib/python3.12/site-packages/xonsh… │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /Users/noor/.virtualenvs/xonfig-NTkDZBCY-py3.12/lib/python3.12/site-packages/xonsh/procs/specs.p │
│ y:897 in run_subproc                                                                             │
│                                                                                                  │
│   894 │   │   │   # from commands such as `rm -i` (see #1436)                                    │
│   895 │   │   │   XSH.shell.settitle()                                                           │
│   896 │   │   │   # run the subprocess                                                           │
│ ❱ 897 │   │   │   return _run_specs(specs, cmds)                                                 │
│   898 │   else:                                                                                  │
│   899 │   │   return _run_specs(specs, cmds)                                                     │
│   900                                                                                            │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ captured = 'hiddenobject'                                                                    │ │
│ │     cmds = (['git-cola', ('2>', '/dev/null')], '&')                                          │ │
│ │     envs = None                                                                              │ │
│ │    specs = [                                                                                 │ │
│ │            │   SubprocSpec(['/opt/homebrew/Cellar/git-cola/4.6.1/libexec/bin/python',        │ │
│ │            '/opt/homebrew/bin/git-cola'], Popen, stdin=None, stdout=None,                    │ │
│ │            stderr=<_io.TextIOWrapper name='/dev/null' mode='w' encoding='UTF-8'>,            │ │
│ │            universal_newlines=False, close_fds=False)                                        │ │
│ │            ]                                                                                 │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /Users/noor/.virtualenvs/xonfig-NTkDZBCY-py3.12/lib/python3.12/site-packages/xonsh/procs/specs.p │
│ y:911 in _run_specs                                                                              │
│                                                                                                  │
│   908 │   proc = command.proc                                                                    │
│   909 │   background = command.spec.background                                                   │
│   910 │   if not all(x.is_proxy for x in specs):                                                 │
│ ❱ 911 │   │   xj.add_job(                                                                        │
│   912 │   │   │   {                                                                              │
│   913 │   │   │   │   "cmds": cmds,                                                              │
│   914 │   │   │   │   "pids": [i.pid for i in command.procs],                                    │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ background = True                                                                            │ │
│ │   captured = 'hiddenobject'                                                                  │ │
│ │       cmds = (['git-cola', ('2>', '/dev/null')], '&')                                        │ │
│ │    command = <class 'rich.pretty.Node'>.__repr__ returned empty string                       │ │
│ │       proc = <Popen: returncode: None args:                                                  │ │
│ │              ['/opt/homebrew/Cellar/git-cola/4.6.1/libexec...>                               │ │
│ │      specs = [                                                                               │ │
│ │              │   SubprocSpec(['/opt/homebrew/Cellar/git-cola/4.6.1/libexec/bin/python',      │ │
│ │              '/opt/homebrew/bin/git-cola'], Popen, stdin=None, stdout=None,                  │ │
│ │              stderr=<_io.TextIOWrapper name='/dev/null' mode='w' encoding='UTF-8'>,          │ │
│ │              universal_newlines=False, close_fds=False)                                      │ │
│ │              ]                                                                               │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /Users/noor/.virtualenvs/xonfig-NTkDZBCY-py3.12/lib/python3.12/site-packages/xonsh/jobs.py:376   │
│ in add_job                                                                                       │
│                                                                                                  │
│   373 │   get_tasks().appendleft(num)                                                            │
│   374 │   get_jobs()[num] = info                                                                 │
│   375 │   if info["bg"] and XSH.env.get("XONSH_INTERACTIVE"):                                    │
│ ❱ 376 │   │   print_one_job(num)                                                                 │
│   377                                                                                            │
│   378                                                                                            │
│   379 def clean_jobs():                                                                          │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ info = {                                                                                     │ │
│ │        │   'cmds': (['git-cola', ('2>', '/dev/null')], '&'),                                 │ │
│ │        │   'pids': [17996],                                                                  │ │
│ │        │   'obj': <Popen: returncode: None args:                                             │ │
│ │        ['/opt/homebrew/Cellar/git-cola/4.6.1/libexec...>,                                    │ │
│ │        │   'bg': True,                                                                       │ │
│ │        │   'pipeline': ,                                                                     │ │
│ │        │   'pgrp': 17996,                                                                    │ │
│ │        │   'started': 1712666211.159474,                                                     │ │
│ │        │   'status': 'running'                                                               │ │
│ │        }                                                                                     │ │
│ │  num = 2                                                                                     │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /Users/noor/.virtualenvs/xonfig-NTkDZBCY-py3.12/lib/python3.12/site-packages/xonsh/jobs.py:354   │
│ in print_one_job                                                                                 │
│                                                                                                  │
│   351                                                                                            │
│   352 def print_one_job(num, outfile=sys.stdout):                                                │
│   353 │   """Print a line describing job number ``num``."""                                      │
│ ❱ 354 │   info = format_job_string(num)                                                          │
│   355 │   if info:                                                                               │
│   356 │   │   print(info, file=outfile)                                                          │
│   357                                                                                            │
│                                                                                                  │
│ ╭──────────────────────────────── locals ─────────────────────────────────╮                      │
│ │     num = 2                                                             │                      │
│ │ outfile = <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'> │                      │
│ ╰─────────────────────────────────────────────────────────────────────────╯                      │
│                                                                                                  │
│ /Users/noor/.virtualenvs/xonfig-NTkDZBCY-py3.12/lib/python3.12/site-packages/xonsh/jobs.py:346   │
│ in format_job_string                                                                             │
│                                                                                                  │
│   343 │   tasks = get_tasks()                                                                    │
│   344 │   pos = "+" if tasks[0] == num else "-" if tasks[1] == num else " "                      │
│   345 │   status = job["status"]                                                                 │
│ ❱ 346 │   cmd = " ".join([" ".join(i) if isinstance(i, list) else i for i in job["cmds"]])       │
│   347 │   pid = job["pids"][-1]                                                                  │
│   348 │   bg = " &" if job["bg"] else ""                                                         │
│   349 │   return f"[{num}]{pos} {status}: {cmd}{bg} ({pid})"                                     │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │    job = {                                                                                   │ │
│ │          │   'cmds': (['git-cola', ('2>', '/dev/null')], '&'),                               │ │
│ │          │   'pids': [17996],                                                                │ │
│ │          │   'obj': <Popen: returncode: None args:                                           │ │
│ │          ['/opt/homebrew/Cellar/git-cola/4.6.1/libexec...>,                                  │ │
│ │          │   'bg': True,                                                                     │ │
│ │          │   'pipeline': ,                                                                   │ │
│ │          │   'pgrp': 17996,                                                                  │ │
│ │          │   'started': 1712666211.159474,                                                   │ │
│ │          │   'status': 'running'                                                             │ │
│ │          }                                                                                   │ │
│ │    num = 2                                                                                   │ │
│ │    pos = '+'                                                                                 │ │
│ │ status = 'running'                                                                           │ │
│ │  tasks = deque([2, 1])                                                                       │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
TypeError: sequence item 1: expected str instance, tuple found

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unable to pass a single ">" as an argument
4 participants