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

[bugfix] Using unlisted_choice a second time doesn't work #766

Merged
merged 4 commits into from Aug 22, 2023

Conversation

GeorgianaElena
Copy link
Member

@GeorgianaElena GeorgianaElena commented Aug 21, 2023

Multiple usages of the unlisted_choice option result in the same first introduced input to be used. If another pre-selected image is used, that works.

This is because we're assuming to find the default {value} of the override, which is not the case after the first override was applied. EDIT: because we worked on an object that shouldn't be changed instead of a copy by mistake

This PR:

  • updated a test to use unlisted_choice a second time to reproduce the bug
  • fixes the bug by just overriding whatever was before with the user's input, not assuming anything about the format of the existing value

Reference: 2i2c-org/infrastructure#2887 and #772

@consideRatio
Copy link
Member

I'm catching up a bit with how this is implemented initially and just learned about the {value} part.

- `unlisted_choice`: Object to specify if there should be a free-form field if the user
selected "Other" as a choice:
- `enabled`: Boolean, whether the free form input should be enabled
- `display_name`: String, label for input field
- `validation_regex`: Optional, regex that the free form input should match - eg. ^pangeo/.*$
- `validation_message`: Optional, validation message for the regex. Should describe the required
input format in a human-readable way.
- `kubespawner_override`: Object specifying what key:values should be over-ridden
with the value of the free form input, using `{value}` for the value to be substituted with
the user POSTed value in the `unlisted_choice` input field. eg:
- some_config_key: some_value-with-{value}-substituted-with-what-user-wrote

My understanding is that this PR breaks the documented behavior of reading both keys and values in kubespawner_override, to just reading the key.

Here is a snippet from a test config that helps me think. I understand it as it won't matter what we set as a value to the image key on line 54:

'profile_options': {
'image': {
'display_name': 'Image',
'unlisted_choice': {
'enabled': True,
'display_name': 'Image Location',
'validation_regex': '^pangeo/.*$',
'validation_message': 'Must be a pangeo image, matching ^pangeo/.*$',
'kubespawner_override': {'image': '{value}'},
},

How flexible do we want this feature to be?

  • Before this PR the unlisted choice could update multiple string based configs based on string templates.
  • After this PR the unlisted choice could update multiple string based configs - but only directly based on the provided value.

I'm fine with the idea of reducing the complexity to no longer supporting the string templates as I think this PR does. If we go for that and I understood how things worked, the docs should just be updated first to not mention {value} etc I think.

@yuvipanda
Copy link
Collaborator

Thanks for digging into this, @GeorgianaElena!

I would love for us to keep the {value} if possible.

Do you know why this behavior differs on first use vs second?

@GeorgianaElena
Copy link
Member Author

@yuvipanda, @consideRatio, I think I found the actual culprit. The part where the dict of overrides is constructed:

for k, v in chosen_option_overrides.items():
chosen_option_overrides[k] = v.format(
value=selected_profile_user_options[
unlisted_choice_form_key
]
)

wasn't the issue.
Instead this was the place where the original self.profile_list dict was updated to hold the actual override instead of the initial {value}. This is because the function was passed a reference to the self.profile_list dict, instead of a copy of it. So chosen_option_overrides is a reference to a dict inside self.profile_list and we're actually modifying it here.

Copy link
Member

@consideRatio consideRatio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work figuring this out @GeorgianaElena, it looks great!

@consideRatio consideRatio merged commit 297cb3f into jupyterhub:main Aug 22, 2023
9 checks passed
@GeorgianaElena GeorgianaElena deleted the unlisted-twice branch August 22, 2023 08:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants