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

Removed mechanism that change $PATH #148

Merged
merged 5 commits into from
Jun 19, 2019

Conversation

xmnlab
Copy link
Contributor

@xmnlab xmnlab commented Apr 4, 2019

resolves #145

@xmnlab
Copy link
Contributor Author

xmnlab commented Apr 4, 2019

the error on CI for python 3.3 says: RuntimeError: Python 3.4 or later is required

any thoughts?

It seems it is done for review.

@gnestor
Copy link

gnestor commented Apr 9, 2019

@xmnlab Your PR looks good.

It looks like master is failing CI: https://travis-ci.org/jupyter/jupyter_core/builds/443142041

@minrk Any ideas?

@minrk
Copy link
Member

minrk commented Apr 9, 2019

We need to make sure that this doesn't change the resolution of executables, which it looks like it does, currently. I think this change currently requires all jupyter-foo to be in the same directory as jupyter, which would not be correct.

The behavior should be the same as if dirname(jupyter) is on PATH. So what we need to do is find jupyter-foo on $PATH+dirname(jupyter) and then resolve the absolute path, but without mutating $PATH. This needs to be careful to properly resolve with $PATHEXT on Windows.

One option, I believe, should be to use shutil.which to resolve the path:

with mock.patch($PATH with self):
    abs_exe = shutil.which(jupyter-foo)
if abs_exe:
    exec(abs_exe)

@xmnlab
Copy link
Contributor Author

xmnlab commented Apr 12, 2019

thanks @minrk for the feedback. I hope to have captured your thoughts. let me know if I understood that correctly.

@xmnlab
Copy link
Contributor Author

xmnlab commented Apr 13, 2019

regarding to https://pypi.org/project/setuptools/ it seems py3.3 is not supported any more.

@xmnlab
Copy link
Contributor Author

xmnlab commented Apr 13, 2019

it is done for a new review.

# set new PATH with self
os.environ['PATH'] = os.pathsep.join(_path_with_self())
# get the real path for the jupyter-<subcommand>
real_path = find_executable('{}-{}'.format(path, subcommand))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

shutil.which is not available for py2

Copy link
Member

Choose a reason for hiding this comment

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

But good news, this repo already has a backport - from .utils.shutil_which import which. This is a bit more complex than find_executable, e.g. it handles PATHEXT on Windows, so it would be good to use that (and the real shutil.which on Python 3, of course).

@xmnlab
Copy link
Contributor Author

xmnlab commented Apr 17, 2019

any feedback?

@xmnlab
Copy link
Contributor Author

xmnlab commented Apr 22, 2019

hey everyone, any feedback about this PR?

@xmnlab
Copy link
Contributor Author

xmnlab commented Apr 24, 2019

hey @Carreau ! @gnestor told me maybe you could help with some review/feedback

@xmnlab
Copy link
Contributor Author

xmnlab commented Apr 30, 2019

hey everyone! any thoughts here?

@gnestor
Copy link

gnestor commented Apr 30, 2019

@takluyver Would you care to review?

@takluyver
Copy link
Member

Yup, I'll review. While we're looking at this repository, can I encourage people to consider PR #143?

Copy link
Member

@takluyver takluyver left a comment

Choose a reason for hiding this comment

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

Thanks, the idea looks fine, but I've left a few notes about the implementation.

# set new PATH with self
os.environ['PATH'] = os.pathsep.join(_path_with_self())
# get the real path for the jupyter-<subcommand>
real_path = find_executable('{}-{}'.format(path, subcommand))
Copy link
Member

Choose a reason for hiding this comment

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

But good news, this repo already has a backport - from .utils.shutil_which import which. This is a bit more complex than find_executable, e.g. it handles PATHEXT on Windows, so it would be good to use that (and the real shutil.which on Python 3, of course).

jupyter_core/command.py Outdated Show resolved Hide resolved
jupyter_core/command.py Outdated Show resolved Hide resolved
@@ -113,9 +115,24 @@ def _execvp(cmd, argv):
os.execvp(cmd, argv)


def _jupyter_realpath(path, subcommand):
Copy link
Member

Choose a reason for hiding this comment

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

This should have a brief docstring to explain what it is.

@xmnlab
Copy link
Contributor Author

xmnlab commented Jun 11, 2019

thanks for the feedback @takluyver i will work on that!

@xmnlab
Copy link
Contributor Author

xmnlab commented Jun 11, 2019

@takluyver @minrk @gnestor it is done for a new review :)

jupyter_core/command.py Outdated Show resolved Hide resolved

command = 'jupyter-' + subcommand

command = _jupyter_abspath(sys.argv[0], subcommand)
Copy link
Member

Choose a reason for hiding this comment

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

I think we always want to be looking up jupyter-xyz, regardless of what sys.argv[0] is.

Copy link
Contributor Author

@xmnlab xmnlab Jun 17, 2019

Choose a reason for hiding this comment

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

@takluyver I changed that considering the follow case reported by @mlucool

Setup:

  1. Set your PATH to have python 2 as your default version of python (prepend the path)
  2. Run jupyterlab from a python 3 location (e.g. `path/to/python-3/bin/jupyterlab')
  3. In a python 2 kernel run the following:
import sys
print(sys.version)
import os
print(os.environ['PATH'])

As expected, sys.version will be python 2. But now you can see that the PATH is modified with python3 in preprended. So if I were to do:

import subprocess
print(subprocess.Popen("python -c 'import sys; print(sys.version)'", shell=True, stdout=subprocess.PIPE).stdout.read())

This would show python 3.

This is really just a problem as we are migrating from python 2 to 3 and we want to run the server with 3 (as we want to use latest) but anything that is called via subprocess should use whatever you had in your PATH. We are planning to locally path ipykernel_launcher.py in a hacky way. This is suboptiomal so we'd like to revert this as soon as we can.

maybe it will not be a problem considering that there is no jupyterlab for py2 .. but if path/to/python-3/bin/jupyterlab is not in $PATH even if I run jupyerlab using the full path it will not be found.

do you have any thoughts here, considering this case?

Copy link
Member

Choose a reason for hiding this comment

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

I'm fine with not modifying $PATH.

The sys.argv[0] that you pass in here is only used, as far as I can see, in this line:

jupyter_subcommand = '{}-{}'.format(path, subcommand)

If sys.argv[0] is, e.g. /home/takluyver/.local/bin/jupyter, then you construct a subcommand like /home/takluyver/.local/bin/jupyter-notebook. That short-circuits shutil.which(), so it will only work if that's the location of jupyter-notebook.

If the subcommand is notebook, then we should always be looking up jupyter-notebook, not {sys.argv[0]}-notebook.

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 see .. OK .. so maybe related to the scenario presented by @mlucool the workaround should be call /path/jupyterlab-subcommand directly

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@takluyver it is done for a new review! thanks!

@takluyver takluyver added this to the 4.5 milestone Jun 13, 2019
# get env PATH with self
search_path = os.pathsep.join(_path_with_self())
# get the abs path for the jupyter-<subcommand>
jupyter_subcommand = '{}-{}'.format(path, subcommand)
Copy link
Member

Choose a reason for hiding this comment

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

Thanks. Now you don't need to pass an argument, you can just hardcode it in this line. That's one less thing to follow around when reading the code. :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok :) done!

@@ -113,9 +119,29 @@ def _execvp(cmd, argv):
os.execvp(cmd, argv)


def _jupyter_abspath(subcommand):
"""This method get the abspath of jupyter with no changes on ENV."""
Copy link
Member

Choose a reason for hiding this comment

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

Nitpick: "...the abspath of a specified jupyter-subcommand..."

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok! done! thanks for the feedback!

@takluyver
Copy link
Member

Thanks! I've just spotted that the docstring should be a bit clearer. Other than that, I think this looks good.

@gnestor @minrk - once this is landed, I'll probably try to make a 4.5.0 release soon.

@takluyver takluyver merged commit 2ae0172 into jupyter:master Jun 19, 2019
@xmnlab xmnlab deleted the mutating-env-path branch June 19, 2019 14:40
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.

Mutating environ PATH's side effects
4 participants