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

implement pseudo tty on stdout/stderr #2711

Merged
merged 3 commits into from Dec 16, 2022
Merged

implement pseudo tty on stdout/stderr #2711

merged 3 commits into from Dec 16, 2022

Conversation

masenf
Copy link
Collaborator

@masenf masenf commented Dec 14, 2022

Thanks for contribution

Please, make sure you address all the checklists (for details on how see
development documentation)!

  • ran the linter to address style issues (tox -e fix)
  • wrote descriptive pull request text
  • ensured there are test(s) validating the fix
  • added news fragment in docs/changelog folder
  • updated/extended the documentation

pty

This is my first attempt at fixing #1773, starting with the example code posted on that issue, and adapting it for some changes that have occured since then.

For the most part the code worked really nice already.

I did encounter the one problem mentioned after setting the Popen stdout and stderr handles to pty:

but once done that the stdin echo seems to no longer buffer realtime, and is instead only line-buffered. This is bad for interacting with the GDB

After lots of poking around, I determine that the code in SyncWrite, which is supposed to write the content to the target after some minimum delay, was not restarting its timer appropriately, causing the output to "hang" until SyncWrite discovered a newline \n.

With that fix in 9b06df5, everything seems to be working fine, EXCEPT, the log files now have ANSI escape sequences in them... which may or may not be desirable. After all, that is what the program output.

After this patch, colored output and interactive use (pdb, ipython) appears to be working out of the box!

Testing

Here's my "human" test file with 4 cases, to exemplify the differences between tox 3, tox 4, and this patch.

I've made these sort of non-scientific comparisons on a macOS 10.15 machine.

[tox]
skipsdist = true
envlist = py, pytest, textual, vim

[testenv]
commands =
    python -i -c 'import sys; \
        print("sys.stdout.isatty(): %s" % sys.stdout.isatty()); \
        print("to stdout, should be colorless\n"); \
        print("sys.stderr.isatty(): %s" % sys.stderr.isatty()); \
        print("to stderr, should be red?\n", file=sys.stderr)'

[testenv:pytest]
deps = pytest
commands =
    pytest {posargs} --pdb

[testenv:textual]
deps = textual
commands =
    python -m textual

[testenv:vim]
allowlist_externals = vim
commands = vim -p /tmp/f1 /tmp/f2 /tmp/f3

tox 3 ("current behavior" expected by users)

  • py
    • sys.stdout.isatty(): True
    • sys.stderr.isatty(): True
    • printed lines are in order
    • session is interactive, arrow keys work, input is echoed
    • stderr is not colored red (that's a tox4 feature)
  • pytest
    • color output (green dots, red F, and red Failed: text
    • pdb session is interactive, arrow keys work, input is echoed
  • textual
    • demo works, but appears to be in "low color" or "reduced feature" mode
  • vim: fully interactive, working as expected

tox 3 (Using tee to pipe the output to a log file)

  • py
    • sys.stdout.isatty(): False
    • sys.stderr.isatty(): False
    • printed lines out of order (after pressing <enter>)
    • session is non-interactive, arrow keys print control codes, input is echoed, but stdout is block buffered and output is delayed to screen.
  • pytest
    • monochrome output
    • pdb session is non-interactive, arrow keys print control codes
  • textual
    • surprisingly, demo works. still in "low color" or "reduced feature" mode and small fixed window size (toggle light/dark mode fixes window size)
  • vim: fully interactive, working as expected (also surprising)

tox 4 ("new behavior" shows some regression in expected functionality)

  • py
    • stderr is colored red
    • printed lines out of order (pressing <enter> shows previous output)
    • sys.stdout.isatty(): False
    • sys.stderr.isatty(): False
    • session is non-interactive, arrow keys print control codes. input is echoed, but stdout and stderr are buffered unexpectedly (for example: the prompt doesn't show up until a newline appears on stderr)
  • pytest
    • familiar dot and status letters are monochrome; stderr is red (as expected)
    • pdb session is not interactive, arrow keys print control codes
  • textual
    • surprisingly, demo works basically perfectly. not sure how they pulled that off 🤯
  • vim
    • sort of works (better than expected), but there are still delayed output issues, sometimes nothing shows up when you type. However, switching tabs (gt and gT can sometimes trigger a refresh).

tox 4 (Using tee to pipe the output to a log file)

  • py: no change using tee
  • pytest: no change using tee
  • textual: behaves like tox 3 with tee
  • vim: no change using tee

tox 4 with this patch!

  • py
    • sys.stdout.isatty(): True
    • sys.stderr.isatty(): True
    • stderr text is colored red
    • session is interactive, arrow keys work, input is echoed
  • pytest
    • color output (green dots, red F, and red Failed: text
    • pdb session is interactive, arrow keys work, input is echoed
  • textual
    • demo works perfectly, no change from tox 4; using high color mode, unlike tox 3.
  • vim: fully interactive, working as expected

tox 4 with this patch! (Using tee to pipe the output to a log file)

  • py
    • sys.stdout.isatty(): False
    • sys.stderr.isatty(): True
    • monochrome output
    • session is non-interactive, arrow keys print control codes. input is echoed; not observing any buffering issues (likey SyncWrite fix at work)
  • pytest
    • monochrome output
    • pdb session is non-interactive, arrow keys print control codes
  • textual: behaves like tox 3 with tee
  • vim: fully interactive, working as expected (again, not sure how, but i'll take it)

TODO

  • Failing test to investigate turned out to be a macOS issue with homebrew-installed python interpreters. The test was expecting the executable to be /usr/local/opt/python@3.11/bin/python3.11, but when it runs throught the virtualenv, the path name comes out as /usr/local/Cellar/python@3.11/3.11.0/Frameworks/Python.framework/Versions/3.11/bin/python3.11... These are both hardlinks to the same inode. Not reproducing on linux.
  • Additional test coverage for this feature added to existing test_local_subprocess_tty
  • Testing on other platforms:
    • windows
    • linux
    • pypy

during SyncWrite.handler (post-lock):
  * cancel the timer thread
  * if a newline was found, _write up to the newline
  * unconditionally start the timer to sweep up any remaining output
    after some delay

This facilitates interactive use of tox commands.
The purpose of allocating a pty is to allow better interactive use and
enable commands to detect that they are running interactively.

Based on starter code on issue tox-dev#1773. Fixes issue tox-dev#1773.
@gaborbernat gaborbernat merged commit 36ec2c0 into tox-dev:main Dec 16, 2022
@masenf masenf deleted the pty branch December 16, 2022 16:03
descope bot added a commit to descope/django-descope that referenced this pull request Dec 30, 2022
This PR contains the following updates:

| Package | Type | Update | Change | Pending |
|---|---|---|---|---|
| [tox](https://togithub.com/tox-dev/tox) | dev | patch | `4.0.11` ->
`4.0.12` | `4.1.1` (+8) |

---

### Release Notes

<details>
<summary>tox-dev/tox</summary>

### [`v4.0.12`](https://togithub.com/tox-dev/tox/releases/tag/4.0.12)

[Compare
Source](https://togithub.com/tox-dev/tox/compare/4.0.11...4.0.12)

#### What's Changed

- Fix legacy flags, deprecate them and remove --index-url by
[@&#8203;gaborbernat](https://togithub.com/gaborbernat) in
[tox-dev/tox#2731
- syntax fix for tox 4 - CLI args section by
[@&#8203;evgeni](https://togithub.com/evgeni) in
[tox-dev/tox#2734
- implement pseudo tty on stdout/stderr by
[@&#8203;masenf](https://togithub.com/masenf) in
[tox-dev/tox#2711
- Document user level config by
[@&#8203;ziima](https://togithub.com/ziima) in
[tox-dev/tox#2736
- Fix python hash seed not being set by
[@&#8203;gaborbernat](https://togithub.com/gaborbernat) in
[tox-dev/tox#2739

#### New Contributors

- [@&#8203;evgeni](https://togithub.com/evgeni) made their first
contribution in
[tox-dev/tox#2734

**Full Changelog**:
tox-dev/tox@4.0.11...4.0.12

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNC43NC4wIiwidXBkYXRlZEluVmVyIjoiMzQuNzQuMCJ9-->

Co-authored-by: descope[bot] <descope[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants