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: shortcut error in loop #340

Closed
wants to merge 2 commits into from
Closed

Conversation

weiduhuo
Copy link
Contributor

What is the problem that this PR addresses?

When we use the select method within a loop, and the Choice parameter sequence is defined outside the loop, shortcut keys in alternating loops are presented in a doubled manner of the actual values.

example:

import questionary
from questionary import Choice

options = [Choice("One"), Choice("Two"), Choice("Three")]
for _ in range(4):
    option = questionary.select("Title:", options, use_shortcuts=True).ask()

2023-11-28-3421

How did you solve it?

The root cause is that, during the initialization of the InquirerControl.choices in the _init_choices process, when a Choice object is instantiated with another Choice object as a parameter, it directly references and passes the return result. This causes the shortcut_key parameter state of the Choice object to be retained in the loop, leading to the aforementioned issue.
We can resolve this issue by modifying the build method of the Choice class. When accepting a Choice-type parameter, we can return the result using a shallow copy."

import copy

if isinstance(c, Choice):
   return copy.copy(c)

Checklist

  • I have read the Contributor's Guide.
  • I will check that all automated PR checks pass before the PR gets reviewed.

@kiancross
Copy link
Collaborator

Thanks for spotting this bug and submitting a PR. From what I understand, the problem is as follows:

  1. When a Choice is instantiated without a shortcut, Choice.shortcut_key is None and so Choice.auto_shortcut is set to True.
  2. Choices passed to InquirerControl are untouched if they are an instance of a Choice (and so any changes made to the choice by InquirerControl are preserved across calls).
  3. _assign_shortcut_keys iterates through choices and removes shortcuts which have already been assigned from the list.
  4. Remaining shortcuts are then assigned to choices with auto_shortcut set to True.

The problem occurs on subsequent calls to (3) and (4).

I see a few possible solutions:

  1. The one you have proposed.
  2. Once Choice.shortcut_key is set, Choice.auto_shortcut should be set to False. So the following logic should be moved into a setter for Choice.shortcut_key:
    if shortcut_key is not None:
    if isinstance(shortcut_key, bool):
    self.auto_shortcut = shortcut_key
    self.shortcut_key = None
    else:
    self.shortcut_key = str(shortcut_key)
    self.auto_shortcut = False
    else:
    self.shortcut_key = None
    self.auto_shortcut = True
  3. Either adding and not c.auto_shortcut here:
    if c.shortcut_key is not None:

    or c.shortcut_key is not None here:
    if c.auto_shortcut and not c.disabled:

What do you think?

overhacked added a commit to overhacked/questionary that referenced this pull request Jan 9, 2024
Ensures that `Choice.auto_shortcut` is set to `False` whenever `Choice.shortcut_key` is set to a `str` value and vice versa

Closes tmbo#340
overhacked added a commit to overhacked/questionary that referenced this pull request Jan 9, 2024
Ensures that `Choice.auto_shortcut` is set to `False`
whenever `Choice.shortcut_key` is set to a `str` value
and vice versa.

Closes tmbo#340
overhacked added a commit to overhacked/questionary that referenced this pull request Jan 9, 2024
Ensures that `Choice.auto_shortcut` is set to `False`
whenever `Choice.shortcut_key` is set to a `str` value
and vice versa. Add tests for fix.

Closes tmbo#340
overhacked added a commit to overhacked/questionary that referenced this pull request Jan 9, 2024
Ensures that `Choice.auto_shortcut` is set to `False`
whenever `Choice.shortcut_key` is set to a `str` value
and vice versa. Add tests for fix.

Closes tmbo#340
overhacked added a commit to overhacked/questionary that referenced this pull request Jul 9, 2024
Ensures that `Choice.auto_shortcut` is set to `False`
whenever `Choice.shortcut_key` is set to a `str` value
and vice versa. Add tests for fix.

Fixes tmbo#340

Signed-off-by: Ross Williams <ross@ross-williams.net>
overhacked added a commit to overhacked/questionary that referenced this pull request Jul 17, 2024
Ensures that `Choice.auto_shortcut` is set to `False`
whenever `Choice.shortcut_key` is set to a `str` value
and vice versa. Add tests for fix.

Fixes tmbo#340

Signed-off-by: Ross Williams <ross@ross-williams.net>
@kiancross kiancross closed this in f6761e2 Jul 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants