- Notifications
You must be signed in to change notification settings - Fork 222
Fix stdout color support check #2540
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
Conversation
Currently `canUseSpecialChars` returns `true` when not in Windows and not in tests of the package itself. This causes color codes to be printed when stdout is redirected or piped. Fix it by checking if stdout is a tty. If it is, then we assume that most terminals today support colors and return `true`. (We can't use the standard library `supportsAnsiEscapes` as it only returns `true` when `$TERM` is `xterm`, see dart-lang/sdk#31606.) Also fix the extended reporter's color support flag initialization, which was hard-coded as `true`. Fixes dart-lang#19.
PR HealthChangelog Entry ✔️
Changes to files need to be accounted for in their respective changelogs. This check can be disabled by tagging the PR with |
/// https://github.com/dart-lang/sdk/issues/31606 | ||
bool get canUseSpecialChars => | ||
(!Platform.isWindows || stdout.supportsAnsiEscapes) && !inTestTests; | ||
!Platform.isWindows && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like it will cause a regression on windows by disabling it always.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll update this check as before on Windows.
Mac has the same issue as Linux as it compares the TERM with a 4 known TERM values that no one uses. (in TermIsKnownToSupportAnsi
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fix should just be to delete this line entirely afaik
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah based on the discussion in the SDK issue and the linked stack overflow thread I'm inclined to change this to just the stdioType(stdout) == StdioType.terminal
check and our testing workaround. I think we can drop the windows specific behavior. I don't think we need to wait for a decision SDK changes, we can make the update here now.
I'm also comfortable with the risk of making this change now. I think it's unlikely to break any workflows, and if it does I think it's OK to require a --no-color
or --color
flag to override.
In general, if we believe this is a better way of checking for ansii escape code support, then this should be the std library implementation? I am pretty hesitant to have special behavior here. What happens if you just remove the |
The problem is not with the Windows check. There are two problems:
I can't fix just (1) because then it starts using the wrong code in (2) and I never get any colors. So this fixes both in one PR. I can't separate the two if that's helpful, but we would need to merge (2) first, then (1), to avoid having a state in between that's even worse than the current state.
See github.com/dart-lang/sdk/issues/31606. We could implement this properly in the standard library but it won't be trivial. Instead the applications can assume that all ttys support colors, like we do here. FWIW I did the same in the SDK's test runner a while ago. We use the same "is tty" check there to enable colors. As I say in the issue, checking color support is not trivial (need to find and parse terminfo), and I doubt there are terminals in use today that don't support colors. Even if the standard library doesn't want to assume all ttys support colors I think we can safely assume it in the applications. |
That is half the problem, the current implementation doesn't even attempt to check for support on non-windows. I am in favor of removing that, fwiw. Your current change makes things worse on windows though by always disabling ansii escape codes on windows, if I read it correctly.
Sure this seems like it should be fixed.
If the better implementation here is just to check if we are attached to any terminal, we should change the SDK implementation to that. We don't have to do a perfect implementation before making it better than what it is today. Otherwise, the argument here is basically that nobody should use that function at all, and so why does it exist? Should it be deprecated? |
Yes, I said the same thing in the link. It's been broken since at least 2017. |
import 'package:test_api/src/backend/declarer.dart'; // ignore: implementation_imports | ||
import 'package:test_api/src/backend/invoker.dart'; // ignore: implementation_imports | ||
| ||
import 'runner/configuration.dart'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't import this here, this library must be cross platform and configuration.dart
imports dart:io
.
We will need a configurable import somewhere if we want to avoid hardcoding this setting - and we'll need to still hardcode it for platforms without dart:io
. I think adding a new library just to handle this indirection is OK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't import this here, this library must be cross platform and configuration.dart imports dart:io.
Just importing dart:io
doesn't cause any issues, and we have only one use site of it in Configuration.load
, which we don't use in scaffolding.
Is this still an issue? I think it could also make sense to just move Configuration.load
to somewhere else and remove dart:io
import from runner/configuration.dart
.
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just importing
dart:io
doesn't cause any issues, and we have only one use site of it inConfiguration.load
, which we don't use in scaffolding.Is this still an issue?
Yes, this is still an issue. We cannot remove the restriction that scaffolding.dart
compiles on every platform, so it may not transitively import dart:io
without platform specific imports.
I think it could also make sense to just move
Configuration.load
to somewhere else and removedart:io
import fromrunner/configuration.dart
.
I don't see how that helps. The specific behavior you are importing this file for uses dart:io
. That behavior that you are using must be implemented behind a platform specific import. There is no way around this since you specifically need dart:io
behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The import restrictions are more clearly guarded in bazel, but they also require specific edits in the BUILD
file that match exactly the platform specific imports in the libraries. You should be able to confirm the broken behavior in either google3 where the build rules will warn you, or with dart test -p chrome
, however the latter doesn't warn early it waits for a slow timeout. We might need to revisit the compilation restrictions for the browser platform to improve the UX.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is still an issue. We cannot remove the restriction that scaffolding.dart compiles on every platform, so it may not transitively import dart:io without platform specific imports.
I don't understand the specific issue, could you elaborate?
You can import dart:io
everywhere, you just can't use it (you get a runtime exception). Do you mean we can accidentally use it if we import it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might need to revisit the compilation restrictions for the browser platform to improve the UX
So it's a bazel/g3 issue? Because I can import dart:io
with dart compile js
and dart compile wasm
just fine locally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can import
dart:io
everywhere, you just can't use it (you get a runtime exception).
This is not universally true.
So it's a bazel/g3 issue? Because I can import
dart:io
withdart compile js
anddart compile wasm
just fine locally.
It will break compatibility with DDC (and therefore build_test
is where we'd see it outside of google3). It will also break compatibility with internal dart2js compiles because we are more strict internally than in the dart compile js
frontend.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW the ahead of time failures during compiles are considered the much more developer friendly UX. The dart compile js
lax behavior was influenced by historical choices. If we get the bandwidth to get around to it we'd like for dart test
to also be strict about imports to dart:io
on the web platform because it's more developer friendly than runtime exceptions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW the ahead of time failures during compiles are considered the much more developer friendly UX
The problem is when you have a third-party transitive import which uses dart:io
(or one of the other libs that are not available everywhere) in a limited way. You have to refactor a bunch of packages that you don't own to be able to compile your app.
But maybe that's not an issue for package:test
.
While we're here we should also add support for checking a BTW I think it'll be easier to land if the 2 changes are split up. We'll need to make sure we're compatible with google3 when we introduce new configurable imports. |
Currently
canUseSpecialChars
returnstrue
when not in Windows and not in tests of the package itself.This causes color codes to be printed when stdout is redirected or piped.
Fix it by checking if stdout is a tty. If it is, then we assume that most terminals today support colors and return
true
.(We can't use the standard library
supportsAnsiEscapes
as it only returnstrue
when$TERM
isxterm
, seedart-lang/sdk#31606.)
Also fix the extended reporter's color support flag initialization, which was hard-coded as
true
.Fixes #19.