[...] while discussing about the implementation of the unlisted_choice logic with @yuvipanda, there was a general conclusion that would be beneficial to have all the logic related to profiles into its own module, as the spawner.py file has grown a lot and it's became harder to follow.
I agree on the conclusion and opened this issue to reflect this.
Overview of profile_list related code
profile_list is a KubeSpawner specific feature not all Spawners have, but its implemented using Spawner base class provided functionality.
Spawner base class functionality
A user interfaceSpawner.options_form enables KubeSpawner to declare a HTML form to be presented when a server is to be started.
Backend parsing of user interface provided form dataSpawner.options_from_form enables KubeSpawner to parse form data into a dictionary for later use, stored by JupyterHub into the non-configurable Spawner.user_options the spawner can adjust based on the provided data. If a REST API request is made to jupyterhub to spawn a server, then the parsing is bypassed.
KubeSpawner logic
A user interface
KubeSpawner provides a default jinja2 template that renders with profile_list being passed to it, allowing the result to become an Spawner.options_form jinja2 template for JupyterHub to render with for_user, user, etc. being passed to it.
KubeSpawner can instead of rendering the default template render another template based on configuring either profile_form_template or additional_profile_form_template_paths.
Backend parsing of user interface provided form data
KubeSpawner provides a way to parse the default UI submitted form data via Spawner.options_from_form
Loading selected profiles
When the UI has been used to pass form data, that has been parsed into the user_options, or when an JupyterHub API request to spawn a server directly passes user_options, then this data is supposed to be accounted for. This is done via an explicit call to KubeSpawner.load_user_options from KubeSpawner._start, which in turn calls _get_profile, _load_profile, and _apply_overrides.
What code to extract?
I think all of the above functions are worth considering extracting from spawner.py and being directly implemented in the KubeSpawner class, but the details to how isn't obvious.
Considerations of a ProfileListSpawnerMixin class
I'd like to consider if we could make a ProfileListSpawnerMixin class and have that solve quite a few things.
We could (?) relocate the profile_list config definition itself to the mixin, but still configure it via c.KubeSpawner.profile_list I think.
We could (?) avoid needing to pass state around by instead referencing self to access the spawner state
We could (?) maybe extract the profile_list functionality from KubeSpawner to other Spawners long term with this strategy
I don't know for that this is viable because I'm unsure about traitlets and Python class inheritance, but I'd love to see an approach like this be considered.
@GeorgianaElena wrote in https://github.com/jupyterhub/kubespawner/pull/774#pullrequestreview-1606707512:
I agree on the conclusion and opened this issue to reflect this.
Overview of profile_list related code
profile_list
is a KubeSpawner specific feature not all Spawners have, but its implemented usingSpawner
base class provided functionality.Spawner base class functionality
Spawner.options_form
enables KubeSpawner to declare a HTML form to be presented when a server is to be started.Spawner.options_from_form
enables KubeSpawner to parse form data into a dictionary for later use, stored by JupyterHub into the non-configurableSpawner.user_options
the spawner can adjust based on the provided data. If a REST API request is made to jupyterhub to spawn a server, then the parsing is bypassed.KubeSpawner logic
profile_list
being passed to it, allowing the result to become anSpawner.options_form
jinja2 template for JupyterHub to render withfor_user
,user
, etc. being passed to it.profile_form_template
oradditional_profile_form_template_paths
.Spawner.options_from_form
user_options
, or when an JupyterHub API request to spawn a server directly passesuser_options
, then this data is supposed to be accounted for. This is done via an explicit call toKubeSpawner.load_user_options
fromKubeSpawner._start
, which in turn calls_get_profile
,_load_profile
, and_apply_overrides
.What code to extract?
I think all of the above functions are worth considering extracting from spawner.py and being directly implemented in the KubeSpawner class, but the details to how isn't obvious.
Considerations of a
ProfileListSpawnerMixin
classI'd like to consider if we could make a ProfileListSpawnerMixin class and have that solve quite a few things.
profile_list
config definition itself to the mixin, but still configure it viac.KubeSpawner.profile_list
I think.self
to access the spawner stateprofile_list
functionality from KubeSpawner to other Spawners long term with this strategyI don't know for that this is viable because I'm unsure about traitlets and Python class inheritance, but I'd love to see an approach like this be considered.