Similar to #827, seeing ANSI colors with --no-color #956

Closed
opened 2024-12-23 03:32:10 +00:00 by lingfish · 7 comments
Contributor

What I'm trying to do and why

Heya, I'm scripting some stuff around info, and when there is errors, I'm seeing a ANSI reset of \x1b[0m in stdout output.

Steps to reproduce

Run borgmatic --no-color info --json from a python subprocess call (expecting an error), seeing the error via stderr (good), but also seeing a mostly empty stdout, but with \x1b[0m.

Actual behavior

As above.

Expected behavior

No ANSI whatsoever, if using --no-color.

Other notes / implementation ideas

No response

borgmatic version

1.9.4

borgmatic installation method

pipx

Borg version

1.4.0

Python version

3.11

Database version (if applicable)

No response

Operating system and version

PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"

### What I'm trying to do and why Heya, I'm scripting some stuff around `info`, and when there is errors, I'm seeing a ANSI reset of `\x1b[0m` in `stdout` output. ### Steps to reproduce Run `borgmatic --no-color info --json` from a python subprocess call (expecting an error), seeing the error via `stderr` (good), but also seeing a *mostly* empty `stdout`, but with `\x1b[0m`. ### Actual behavior As above. ### Expected behavior No ANSI whatsoever, if using `--no-color`. ### Other notes / implementation ideas _No response_ ### borgmatic version 1.9.4 ### borgmatic installation method pipx ### Borg version 1.4.0 ### Python version 3.11 ### Database version (if applicable) _No response_ ### Operating system and version PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
Owner

Thanks for taking the time to file this. Unfortunately I haven't been able to get a repro thus far. Here's what I tried with both borgmatic 1.9.4 and main:

$ python -c "import subprocess; subprocess.check_call('borgmatic --config nope --no-color info --json'.split(' '))" > stdout
nope: No valid configuration files found

summary:
...
$ ls -lh stdout
-rw-r--r-- 1 root root 0 Dec 22 22:09 stdout

So stdout is zero bytes, meaning that there aren't any ANSI codes in it. I've also tried without redirection, and didn't see anything suspicious on the console. If you run that command, do you get a similar result? Or do you see an escape code in the output?

If you do get the same result, then can you give a little more info about your repro? What error are you getting, and what's your config file look like?

Thanks for taking the time to file this. Unfortunately I haven't been able to get a repro thus far. Here's what I tried with both borgmatic 1.9.4 and main: ```bash $ python -c "import subprocess; subprocess.check_call('borgmatic --config nope --no-color info --json'.split(' '))" > stdout nope: No valid configuration files found summary: ... $ ls -lh stdout -rw-r--r-- 1 root root 0 Dec 22 22:09 stdout ``` So stdout is zero bytes, meaning that there aren't any ANSI codes in it. I've also tried without redirection, and didn't see anything suspicious on the console. If you run that command, do you get a similar result? Or do you see an escape code in the output? If you do get the same result, then can you give a little more info about your repro? What error are you getting, and what's your config file look like?
Author
Contributor

Yeah, I get the same result as you.

This is truly doing my head in; I've been changing TERM, setting NO_COLOR (as I use click and rich) selectively culling parts of my app, cannot work it out other than it is indeed borgmatic outputting it -- here's an strace launched from within:

2295789 openat(AT_FDCWD, "/etc/borgmatic.d/someconfig.yaml", O_RDONLY|O_CLOEXEC) = -1 EACCES (Permission denied)
2295789 getpid()                        = 2295789
2295789 getpid()                        = 2295789
2295789 write(2, "/etc/borgmatic/config.yaml /etc/"..., 154) = 154
2295789 getpid()                        = 2295789
2295789 write(2, "\n", 1)               = 1
2295789 getpid()                        = 2295789
2295789 write(2, "summary:\n", 9)       = 9
2295789 write(2, "/etc/borgmatic.d/someconfig.yaml: Ins"..., 81) = 81
2295789 write(2, "/etc/borgmatic.d/anotherconfig.yaml: "..., 84) = 84
2295789 write(2, "/etc/borgmatic/config.yaml /etc/"..., 154) = 154
2295789 getpid()                        = 2295789
2295789 write(2, "\n", 1)               = 1
2295789 getpid()                        = 2295789
2295789 write(2, "Need some help? https://torsion."..., 54) = 54
2295789 write(1, "\33[0m", 4)           = 4

The ANSI can clearly be seen at the end writeing to FD 1.

Yeah, I get the same result as you. This is truly doing my head in; I've been changing `TERM`, setting `NO_COLOR` (as I use `click` and `rich`) selectively culling parts of my app, cannot work it out other than it is indeed `borgmatic` outputting it -- here's an `strace` launched from within: ``` 2295789 openat(AT_FDCWD, "/etc/borgmatic.d/someconfig.yaml", O_RDONLY|O_CLOEXEC) = -1 EACCES (Permission denied) 2295789 getpid() = 2295789 2295789 getpid() = 2295789 2295789 write(2, "/etc/borgmatic/config.yaml /etc/"..., 154) = 154 2295789 getpid() = 2295789 2295789 write(2, "\n", 1) = 1 2295789 getpid() = 2295789 2295789 write(2, "summary:\n", 9) = 9 2295789 write(2, "/etc/borgmatic.d/someconfig.yaml: Ins"..., 81) = 81 2295789 write(2, "/etc/borgmatic.d/anotherconfig.yaml: "..., 84) = 84 2295789 write(2, "/etc/borgmatic/config.yaml /etc/"..., 154) = 154 2295789 getpid() = 2295789 2295789 write(2, "\n", 1) = 1 2295789 getpid() = 2295789 2295789 write(2, "Need some help? https://torsion."..., 54) = 54 2295789 write(1, "\33[0m", 4) = 4 ``` The ANSI can clearly be seen at the end `write`ing to FD 1.
Owner

I've confirmed that locally:

$ python -c "import subprocess; subprocess.check_call('strace borgmatic --config nope --no-color info --json'.split(' '))"
...
write(2, "Need some help? https://torsion."..., 54Need some help? https://torsion.org/borgmatic/#issues
) = 54
ioctl(1, TCGETS, {c_iflag=ICRNL|IXON|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = 0
write(1, "\33[0m", 4)                   = 4

And now I have a fix in main! The problem was that colorama was unconditionally outputting a color reset code at exit. Incidentally, it may make sense to ditch colorama at some point: #958.

This fix will be part of the next release. Thanks again!

I've confirmed that locally: ```bash $ python -c "import subprocess; subprocess.check_call('strace borgmatic --config nope --no-color info --json'.split(' '))" ... write(2, "Need some help? https://torsion."..., 54Need some help? https://torsion.org/borgmatic/#issues ) = 54 ioctl(1, TCGETS, {c_iflag=ICRNL|IXON|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = 0 write(1, "\33[0m", 4) = 4 ``` And now I have a fix in main! The problem was that colorama was unconditionally outputting a color reset code at exit. Incidentally, it may make sense to ditch colorama at some point: #958. This fix will be part of the next release. Thanks again!
witten added the
bug
label 2024-12-24 03:57:41 +00:00
Author
Contributor

We were on the same page, nice one. A pleasure working with you as always Dan!

I've read the other ticket, agreed. I'd like to take a stab at that if you like? I note in there you speak of the size of rich, I personally don't see that as an issue (is your concern around size because you are vendoring?). Happy for me to proceed with rich?

We were on the same page, nice one. A pleasure working with you as always Dan! I've read the other ticket, agreed. I'd like to take a stab at that if you like? I note in there you speak of the size of `rich`, I personally don't see that as an issue (is your concern around size because you are vendoring?). Happy for me to proceed with `rich`?
Owner

Sorry, I just saw this after having already implemented that ticket. My apologies! I ended up just replacing colorama with a handful of color constants.. borgmatic wasn't using a lot of colorama's functionality. And yes, rich seemed like overkill. The size wasn't a huge issue—borgmatic itself doesn't do any vendoring even if third-party packages might—but after looking at rich it seemed like a higher-level library than borgmatic really needed to color a couple of different log types.

Sorry, I just saw this after having already implemented that ticket. My apologies! I ended up just replacing colorama with a handful of color constants.. borgmatic wasn't using a lot of colorama's functionality. And yes, `rich` seemed like overkill. The size wasn't a huge issue—borgmatic itself doesn't do any vendoring even if third-party packages might—but after looking at `rich` it seemed like a higher-level library than borgmatic really needed to color a couple of different log types.
Author
Contributor

All good!

All good!
Owner

Released in borgmatic 1.9.5!

Released in borgmatic 1.9.5!
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: borgmatic-collective/borgmatic#956
No description provided.