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

Added add_to_path option for jupyter_environments #48

Merged
merged 9 commits into from
Jan 27, 2022
Merged

Added add_to_path option for jupyter_environments #48

merged 9 commits into from
Jan 27, 2022

Conversation

t20100
Copy link
Member

@t20100 t20100 commented Jan 26, 2022

This option allows to toggle whether or not the jupyter environment path is prepended to PATH.
For instance, when giving access to Python installed on the system, the virtual environment used for jupyter server should not be added to the PATH.
Custom environments are always added to PATH.

@t20100 t20100 added this to the Next release milestone Jan 26, 2022
@t20100 t20100 requested a review from loichuder January 26, 2022 09:41
@@ -16,5 +16,5 @@
set -euo pipefail

trap 'echo SIGTERM received' TERM

{{prologue}}
Copy link
Member Author

Choose a reason for hiding this comment

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

I used prologue here rather than a more specific implementation to keep close to batchspawner which uses the same.

@@ -55,6 +55,7 @@ class MOSlurmSpawner(SlurmSpawner):
per_key_traits={
"path": traitlets.Unicode(),
"description": traitlets.Unicode(),
"add_to_path": traitlets.Bool(default_value=True),
Copy link
Member Author

Choose a reason for hiding this comment

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

Keeping it optional to avoid a breaking change in the config.

Copy link
Member

@loichuder loichuder left a comment

Choose a reason for hiding this comment

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

I am afraid I don't understand the point of this option: when using a custom env, is there a situation where you would not want to add the path to the shell path ?

@@ -220,6 +221,13 @@ def options_from_form(self, formdata: Dict[str, List[str]]) -> Dict[str, str]:
)[0]
options["environment_path"] = default_venv["path"]

for env in self.partitions[partition]["jupyter_environments"].values():
Copy link
Member

Choose a reason for hiding this comment

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

I don't understand why you need to cycle though the jupyter_environments there. Also, I find the for, else syntax a bit obscure.

Copy link
Member Author

Choose a reason for hiding this comment

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

It's checking whether the path corresponds to a default jupyter_environments or to a custom one.
As it is done now, only the environment_path is passed through the form, so it checks whether this path corresponds to one of the default envs, thus the loop.

If it's a custom one, then it is added to the PATH, if it's one of the defaults it checks add_to_path.

The for else syntax is bit uncommon but it is meant for this case. I'll propose an alternate implementation.

Comment on lines 224 to 230
matching_envs_without_add_to_path = [
env
for env in partition_environments
if env["path"] == options["environment_path"]
and not env.get("add_to_path", True)
]
if not matching_envs_without_add_to_path:
Copy link
Member Author

Choose a reason for hiding this comment

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

I replaced the for .. else pattern with a list filter and a test of list content, hope that's simpler to read.

Copy link
Member Author

Choose a reason for hiding this comment

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

BTW the alternative to looping through the list is to use the path as the key for the jupyter envs and put the key as an id item of the dict.

@t20100 t20100 requested a review from loichuder January 27, 2022 09:16
Copy link
Member

@loichuder loichuder left a comment

Choose a reason for hiding this comment

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

Sorry to be nitpicky but if we don't make things clear right now, I will be completely lost next time I dig into this part 🤓

options["environment_path"] = default_venv["path"]
options["environment_path"] = partition_environments[0]["path"]

# Add environment_path to PATH unless it is in the settings with add_to_path=False
Copy link
Member

Choose a reason for hiding this comment

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

I feel the comment should be more meaningful. We should explain the fact that custom envs are always added to the path and because of this, we must first check if the env is a default env.

And then, if the env is a default env, we check if it should be added to the path or not.

For example. I would rename corresponding_env in corresponding_default_env or matching_default_env.

And then above the condition if matching_default_env is None, I would add the comment Custom env are always added to the PATH

lambda env: env["path"] == options["environment_path"],
partition_environments,
)
if corresponding_env is None or corresponding_env.get("add_to_path", True):
Copy link
Member

Choose a reason for hiding this comment

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

Given you set a default value for the trait add_to_path, is the get(..., True) needed ?

Copy link
Member Author

Choose a reason for hiding this comment

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

I add an issue with that, I didn't investigate where it comes from.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think default_value does not work in this case because it specifies a value inside a dict rather than a trait.

Comment on lines +73 to +80
@traitlets.validate("partitions")
def _validate_partitions(self, proposal):
# Set add_to_path if missing in jupyter_environments
partitions = deepcopy(proposal["value"])
for partition in partitions.values():
for env in partition["jupyter_environments"].values():
env.setdefault("add_to_path", True)
return partitions
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the documented way to handle validation of traitlets.

lambda env: env["path"] == options["environment_path"],
partition_environments,
)
# custom envs are always added to PATH, defaults ones only if add_to_path is True
Copy link
Member Author

Choose a reason for hiding this comment

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

Hope this is clearer, else feel free to provide suggestion

Copy link
Member

Choose a reason for hiding this comment

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

That's great 👍

jupyterhub_moss/spawner.py Show resolved Hide resolved
@t20100 t20100 requested a review from loichuder January 27, 2022 13:28
lambda env: env["path"] == options["environment_path"],
partition_environments,
)
# custom envs are always added to PATH, defaults ones only if add_to_path is True
Copy link
Member

Choose a reason for hiding this comment

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

That's great 👍

@t20100 t20100 merged commit 8c5ab94 into main Jan 27, 2022
@t20100 t20100 deleted the add-path branch January 27, 2022 14:37
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