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
bpo-29854: Print readline version information when running test suite #2618
Conversation
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 would prefer to dump the curses version in test_readline, as done by test_tcl or test_gdb in verbose mode. When a test fails on buildbots, the test is run again in verbose mode. |
I prefer to not make regrtest header too big. |
Why would we want to print curses version in test_readline? Unless I'm missing something, curses doesn't have anything to do with bpo-29854. tcl and gdb are much less common dependencies than readline. readline is probably available on all Unix platforms and I think it makes sense to easily see which version is installed on the host.
Sorry, I don't have time for this kind of bikeshedding. We don't design a production level UI for end users and it's already hard to read outputs of regrrest and Buildbot. I prefer not to spend too much time to find which version of readline installed at http://buildbot.python.org/all/builders/x86%20Tiger%203.x/builds/908/steps/test/logs/stdio Plus, that header has already prints less useful information so I don't think two additional lines would set the world on fire :) |
Oh sorry, I'm always confused between readline and curses, they are the same thing for me, sorry :-) By the way, you should mention bpo-29854 in your PR title. It helps later to get the rationale of a change ;-)
Another issue with importing readline early is that importing a module has side effect, especially readline. See for example http://bugs.python.org/issue19884 and TestReadline.test_init(): this test still fails on our RHEL buildbot, so importing readline still have an annoying side effect of writing a string into stdout. I would prefer to limit imports at regrtest startup, to make it more deterministic.
Would you mind to review my PR #2619? When it will be merged, I can retrieve the libreadline version for you and put it in the issue. |
We discuss this PR on IRC with @berkerpeksag. If imports are done are done in subprocess to prevent side effects, I'm ok to get such change merged ;-) |
Lib/test/libregrtest/main.py
Outdated
import readline | ||
except ImportError: | ||
readline = None | ||
if readline is not None: |
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 line just can be an "else:" no?
Lib/test/libregrtest/main.py
Outdated
rl_version_cmd = """if 1: | ||
try: | ||
import readline | ||
except ImportError: |
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.
Maybe use sys.exit(1) to not try to decode empty stdout in the parent process.
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.
Good point!
Lib/test/libregrtest/main.py
Outdated
@@ -432,6 +433,26 @@ def display_header(self): | |||
print("== encodings: locale=%s, FS=%s" | |||
% (locale.getpreferredencoding(False), | |||
sys.getfilesystemencoding())) | |||
rl_version_cmd = """if 1: |
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 may put the textwrap.dedent() directly here. But do you need "if 1:" in that case?
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.
Do you mean
rl_version_cmd = textwrap.dedent("""
...
""")
?
And, you're right, we don't need if 1:
, thanks!
Lib/test/libregrtest/main.py
Outdated
pass | ||
else: | ||
print(f"== readline version: {rl_version}") | ||
print(f"== readline implementation: {rl_implementation}") |
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.
can you please write both info on a single line?
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.
Sure, what do you thing about the following format?:
== readline: 0x0602 (GNU readline)
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 like it. Maybe just add version somewhere? "== readline: version 0x0602 (GNU readline)"
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.
Done:
== readline: version 0x0602 (GNU readline)
Thanks!
Lib/test/libregrtest/main.py
Outdated
is_editline = readline.__doc__ and "libedit" in readline.__doc__ | ||
print("== readline implementation:", "editline" if is_editline else "GNU readline") | ||
print("editline" if is_editline else "GNU readline") | ||
""" |
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.
It is very hard to read this code like this. The other program that you run should be indented differently from the other code.
Also the code to return the info should be in separate function, and here we can just print the values.
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.
So what you're suggesting is similar to the following snippet, right?
rl_version_cmd = """
def get_rl_info():
# all code is here
return version, implementation
version, implementation = get_rl_info()
print(version)
print(implementation)
"""
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.
Or:
rl_version_cmd = """
def get_rl_info():
# all code is here
return version, implementation
version, implementation = get_rl_info()
print("== readline: version {version} ({implementation})")
"""
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.
More like:
def readline_info():
script = """
import json
import readline
is_editline = readline.__doc__ and "libedit" in readline.__doc__
info = {"version": readline._READLINE_VERSION,
"implementation": "editline" if is_editline else "GNU readline"}
print(json.dumps(info))
"""
c = subprocess.run([sys.executable, "-c", script],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
if c.returncode == 0:
return json.loads(c.stdout.decode())
And use readline_info() in display_header(), or in any other context as needed.
I've addressed all review comments (and hopefully I got @nirs' comment right) Thanks! |
Lib/test/libregrtest/main.py
Outdated
pass | ||
import readline | ||
except ImportError: | ||
sys.exit(1) | ||
else: |
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 remove the try/else/exit, just import readline:
import readline
If import fails, we exit with exit code 1 anyway, no special code needed.
Lib/test/libregrtest/main.py
Outdated
rl_output = subprocess.run([sys.executable, "-c", textwrap.dedent(rl_version_cmd)], | ||
stdout=subprocess.PIPE, stderr=subprocess.PIPE) | ||
if rl_output.returncode == 0: | ||
rl_version_cmd = textwrap.dedent(""" |
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 extra indent make this much more clear, thanks!
Lib/test/libregrtest/main.py
Outdated
print(f"== readline version: {rl_version}") | ||
print(f"== readline implementation: {rl_implementation}") | ||
def get_rl_info(): | ||
is_editline = readline.__doc__ and "libedit" in readline.__doc__ |
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 is now the third place using this horrible doc check. I think we should eliminate this, now, or at least leave a todo and clean up later. Ideally we should have exactly one is_editline() function in cpython.
Lib/test/libregrtest/main.py
Outdated
def get_rl_info(): | ||
is_editline = readline.__doc__ and "libedit" in readline.__doc__ | ||
return f"{readline._READLINE_VERSION:#06x}", "editline" if is_editline else "GNU readline" | ||
rl_version, rl_implementation = get_rl_info() |
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 think we should print the same values ptinted now in test_readline.setupModule
@berkerpeksag do you mean #3075? |
@asottile yes that's what I meant! :) Good catch, thanks. |
No description provided.