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

Update shell config file during installation (bash & zsh) #137

Closed
wants to merge 1 commit into from

Conversation

ianchen-tw
Copy link
Contributor

Fix: #112

For users using the installation script, it is natural that the environment variables will be automatically modified

Outline

  • Modify user's profile based on current shell & system(bash & zsh, currently)

Discussion:

  • Should we add an environment variable, so that users can choose not to modify their shell config profiles?

References

@ianchen-tw ianchen-tw changed the title Update shell config file after installation (bash & zsh) Update shell config file during installation (bash & zsh) Nov 25, 2022
echo "Appending the following lines to $1:"
echo ' # pyenv'
echo ' export PATH="'"$PYENV_ROOT/bin:"'$PATH"'
echo ' eval "$(pyenv init --path)"'
Copy link
Member

Choose a reason for hiding this comment

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

The suggested default is pyenv init -

Copy link

Choose a reason for hiding this comment

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

While this is true, I've had the most success across multiple OS'es using the above, or the above in conjunction with pyenv init -. Maybe that's an issue for a separate thread, though? Are there any disadvantages to including pyenv init --path?

Copy link
Member

@native-api native-api Nov 28, 2022

Choose a reason for hiding this comment

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

Yes. Big disadvantage. That's not the suggested setup. 🙂
The suggested setup is not random. It was worked out based on user input about their use cases, to provide full features, in the vast majority of cases and with minimal side effects.

E.g. it provides shell completion, and it doesn't add duplicate PATH entries in a nested shell.

Copy link

Choose a reason for hiding this comment

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

Sounds good. I'll see if I can replicate some of my issues with this suggested setup.

To be clear, I'm talking about having more success in general with:

eval "$(pyenv init -)"
eval "$(pyenv init --path)"

Over:

eval "$(pyenv init -)"

But maybe this comes down to a debate of where pyenv shims belong in the PATH and of course that will be user-dependent.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

@native-api native-api left a comment

Choose a reason for hiding this comment

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

Thanks for the submission! As this is one of the most requested features, you're eligible for a bounty from donated money when this goes live, if you're interested.

Comment on lines 58 to 62
echo ' # pyenv'
echo ' export PATH="'"$PYENV_ROOT/bin:"'$PATH"'
echo ' eval "$(pyenv init --path)"'
echo ' eval "$(pyenv virtualenv-init -)"'
echo ''
Copy link
Member

Choose a reason for hiding this comment

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

It's probably sufficient to just say which files are being updated, like RVM does.

Copy link
Contributor Author

@ianchen-tw ianchen-tw Dec 25, 2022

Choose a reason for hiding this comment

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


add_userpath() {
OS="$(uname -s)"
CURRENT_SHELL="$(basename "$SHELL")"
Copy link
Member

Choose a reason for hiding this comment

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

Since this is a Bash script, $SHELL would probably always be Bash.
pyenv-init has logic to detect the shell of the parent process.
That said, this logic seems to rather belong in pyenv-init to avoid duplication. E.g. it likewise determines profile files for diffent shells and commands to write -- we just need to actually write them rather than just display.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@native-api,

After inspecting pyenv-init, I think we should just copy the logic of determining user shell directly from it, because:

  1. The script(pyenv-init) is not composed to be sourced by other one, so that we can't simply source it and variables(rc, shell, profile) in our script.
  2. bin/py-installer should be a self-containing script, which could be runned even if pyenv-init changed, so a little duplication might be acceptable.

So here's what I'll try to do next:

  • Copying the logic directly of determining shell & rc files from pyenv-init and put a reference to the original code.
  • Keep the OS variable so that it can better fit mac users.

I'll start working on this if you think it's appropriate

Copy link
Member

Choose a reason for hiding this comment

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

The idea is to add yet another mode to pyenv-init -- e.g. --install -- that would write shell configuration. Just like currently, the installer runs it without arguments and it prints installation instructions.

Apart from avoiding code duplication, we won't need to adapt Pyenv-installer if we change something in the suggested shell configuration.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I copied the shell detection mechanism from pyenv-init in pyenv-installer.

This resolves the issue of pyenv-init being unable to detect the parent of the parent process when invoked through pyenv-installer, as described in my experiment(ianchen-tw#2).

fi
}

if ! command -v pyenv 1>/dev/null; then
Copy link
Member

Choose a reason for hiding this comment

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

What's the logic behind this criterion?

Maybe rather check that shell config files don't have any mention of "pyenv"? Or run a new shell with -i and/or --login and check if anything related to Pyenv is set?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I lost the context of this comment.

Could you check if this still being an issue after reviewing the updated code?
Thanks!

Copy link
Member

Choose a reason for hiding this comment

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

AFAICS, this line is supposed to detect whether we need to add shell configuration stuff, or if it's already present.

I can't see how this test achieves that.

Since there's an infinite variety of setups, perhaps the best way of action is to see how other language managers do this -- to see what measures have proven to be sufficient in practice.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This criterion is based on assumptions of how pyenv-installer might be used:

  1. Most users would run pyenv-installer on a newly configured system (without pyenv installed).
  2. The installer will update shell configuration stuff correctly, therefore pyenv would be detected after restarting the shell.

This criterion is not water-proof, especially for users that rerun the installer many times without restarting their shell. But it's probably the simplest way AFAICS.

bin/pyenv-installer Outdated Show resolved Hide resolved
add_userpath

if ${SRC_WRITTEN}; then
echo "Close and reopen your terminal to start using pyenv" >&2
Copy link
Member

Choose a reason for hiding this comment

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

Restarting the shell is enough.

Copy link
Contributor Author

@ianchen-tw ianchen-tw Dec 25, 2022

Choose a reason for hiding this comment

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

README.rst Outdated
then remove these three lines from ``.bashrc``:
then remove these three lines from your shell config file(``.bashrc``, ``.zshrc``, ``.profile``...):
Copy link
Member

Choose a reason for hiding this comment

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

files

Copy link
Contributor Author

@ianchen-tw ianchen-tw Dec 25, 2022

Choose a reason for hiding this comment

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

@ianchen-tw
Copy link
Contributor Author

Thanks for the submission! As this is one of the most requested features, you're eligible for a bounty from donated money when this goes live, if you're interested.

I would love to, lets continue this conversation once the PR gets accepted

@ianchen-tw ianchen-tw changed the title Update shell config file during installation (bash & zsh) [WIP] Update shell config file during installation (bash & zsh) Dec 1, 2022
@native-api native-api marked this pull request as draft December 1, 2022 18:58
@ianchen-tw
Copy link
Contributor Author

I'm still working on this PR.
Anyone interested in the actual progress can refer to
ianchen-tw#2

@ianchen-tw ianchen-tw changed the title [WIP] Update shell config file during installation (bash & zsh) Update shell config file during installation (bash & zsh) Dec 25, 2022
@ianchen-tw ianchen-tw marked this pull request as ready for review December 25, 2022 10:56
@ianchen-tw
Copy link
Contributor Author

Hello @native-api,

Thank you for your help with writing the pull request for the Pyenv(pyenv/pyenv#2561). I have updated this PR and am hopeful that we can get it to work.

Comment on lines +10 to +17
if [ -z "$shell" ]; then
shell="$(ps -p "$PPID" -o 'args=' 2>/dev/null || true)"
shell="${shell%% *}"
shell="${shell##-}"
shell="${shell:-$SHELL}"
shell="${shell##*/}"
shell="${shell%%-*}"
fi
Copy link
Member

Choose a reason for hiding this comment

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

Why the heck did we export --detect-shell, to be used with eval to boot, if we STILL need this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor Author

@ianchen-tw ianchen-tw Jan 5, 2023

Choose a reason for hiding this comment

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

Considering this example:
Run curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash in zsh.
Just to make sure this scenario would work

Copy link
Member

@native-api native-api Jan 5, 2023

Choose a reason for hiding this comment

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

That just means that --detect-shell needs to do better.

Thanks to eval, it can run code in the same process, evading the "shell of parent of parent" problem.
Just make it output the shell detection code that you've copypasted.

fi
}

if ! command -v pyenv 1>/dev/null; then
Copy link
Member

Choose a reason for hiding this comment

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

AFAICS, this line is supposed to detect whether we need to add shell configuration stuff, or if it's already present.

I can't see how this test achieves that.

Since there's an infinite variety of setups, perhaps the best way of action is to see how other language managers do this -- to see what measures have proven to be sufficient in practice.

Comment on lines +64 to +78
write_source() {
# expand ~ to user's home
local target="${1/#\~/$HOME}"

echo "Update file: $1" >&2

echo "" >>$target
echo '# pyenv' >>$target
echo 'export PATH="'"$PYENV_ROOT/bin:"'$PATH"' >>$target
echo 'eval "$(pyenv init -)"' >>$target
echo 'eval "$(pyenv virtualenv-init -)"' >>$target

USER_PATH_ADDED=true
}

Copy link
Member

Choose a reason for hiding this comment

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

I still heavily dislike the duplication with pyenv-init.
It's going to be a constant headache and source of errors during maintenance.

I understand the desire to keep installation logic out of pyenv-init as it's of no use after installation. But however you look at it, the bulk of it is already in Pyenv-Init anyway!

Copy link
Member

Choose a reason for hiding this comment

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

The "is-Pyenv-shell-setup-already-done" part of the logic is something that could probably be kept out of Pyenv-Init -- if it proves to be different enough from existing Pyenv-Init logic.

Copy link
Member

@native-api native-api Jan 4, 2023

Choose a reason for hiding this comment

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

We could add pyenv init --profile and pyenv init --rc to output just the stuff that needs to be written, then write it here. But since those files are detected inside --detect-shell, it seems simpler and even less code in pyenv-init to just add a single pyenv-init --install.

@native-api
Copy link
Member

I can try to complete the PR myself, addressing the remaining concerns (will probably have time this weekend).

@ianchen-tw
Copy link
Contributor Author

Just wanted to express my thanks to @native-api for continuing to work on my PR and for spending extra time on it.
I really appreciate your dedication to this project and it's great to see any progress that you're making.
Thank you for your efforts!

@ianchen-tw
Copy link
Contributor Author

ianchen-tw commented May 7, 2023

@native-api any update?

If no one is interested in this pull request anymore, I'll likely close it.

@ianchen-tw ianchen-tw closed this May 8, 2023
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.

Pyenv installer does not add to path
3 participants