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

Only prefer envs owned by the current user #323

Merged
merged 8 commits into from
Dec 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion jupyter_core/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,21 +68,49 @@ def get_home_dir() -> str:
_dtemps: Dict[str, str] = {}


def _do_i_own(path: str) -> bool:
"""Return whether the current user owns the given path"""
p = Path(path).resolve()

# walk up to first existing parent
while not p.exists() and p != p.parent:
p = p.parent

# simplest check: owner by name
# not always implemented or available
try:
return p.owner() == os.getlogin()
except (NotImplementedError, OSError):
pass

if hasattr(os, 'geteuid'):
try:
st = p.stat()
return st.st_uid == os.geteuid()
except (NotImplementedError, OSError):
# geteuid not always implemented
pass

# no ownership checks worked, check write access
return os.access(p, os.W_OK)


def prefer_environment_over_user() -> bool:
"""Determine if environment-level paths should take precedence over user-level paths."""
# If JUPYTER_PREFER_ENV_PATH is defined, that signals user intent, so return its value
if "JUPYTER_PREFER_ENV_PATH" in os.environ:
return envset("JUPYTER_PREFER_ENV_PATH") # type:ignore[return-value]

# If we are in a Python virtualenv, default to True (see https://docs.python.org/3/library/venv.html#venv-def)
if sys.prefix != sys.base_prefix:
if sys.prefix != sys.base_prefix and _do_i_own(sys.prefix):
return True

# If sys.prefix indicates Python comes from a conda/mamba environment that is not the root environment, default to True
if (
"CONDA_PREFIX" in os.environ
and sys.prefix.startswith(os.environ["CONDA_PREFIX"])
and os.environ.get("CONDA_DEFAULT_ENV", "base") != "base"
and _do_i_own(sys.prefix)
):
return True

Expand Down
6 changes: 4 additions & 2 deletions jupyter_core/tests/test_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,9 +400,10 @@ def test_prefer_environment_over_user():

# Test default if environment variable is not set, and try to determine if we are in a virtual environment
os.environ.pop("JUPYTER_PREFER_ENV_PATH", None)

# base prefix differs, venv
with patch.object(sys, "base_prefix", "notthesame"):
assert prefer_environment_over_user()
assert prefer_environment_over_user() == paths._do_i_own(sys.prefix)

# conda
with patch.object(sys, "base_prefix", sys.prefix):
Expand All @@ -411,7 +412,8 @@ def test_prefer_environment_over_user():
assert not prefer_environment_over_user()
# in non-base env, prefer it
with patch.dict(os.environ, {"CONDA_PREFIX": sys.prefix, "CONDA_DEFAULT_ENV": "/tmp"}):
assert prefer_environment_over_user()
assert prefer_environment_over_user() == paths._do_i_own(sys.prefix)

# conda env defined, but we aren't using it
with patch.dict(
os.environ, {"CONDA_PREFIX": "/somewherelese", "CONDA_DEFAULT_ENV": "/tmp"}
Expand Down