Skip to content
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
6 changes: 6 additions & 0 deletions .github/workflows/workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ jobs:
run: |
python -m pip install git+https://github.com/emscripten-forge/pyjs-code-runner --no-deps --ignore-installed

# Remove after https://github.com/emscripten-forge/pyjs-code-runner/pull/15 is merged.
- name: Install appdirs
shell: bash -l {0}
run: |
python -m pip install appdirs

- name: Run pytest
shell: bash -l {0}
run: |
Expand Down
85 changes: 83 additions & 2 deletions empack/pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from tempfile import TemporaryDirectory
from typing import Callable, Optional

from appdirs import user_cache_dir
from platformdirs import user_cache_dir

from .filter_env import filter_env, filter_pkg, iterate_env_pkg_meta
from .micromamba_wrapper import create_environment
Expand All @@ -16,7 +16,88 @@
EMPACK_CACHE_DIR = Path(user_cache_dir("empack"))
PACKED_PACKAGES_CACHE_DIR = EMPACK_CACHE_DIR / "packed_packages_cache"
PACKED_PACKAGES_CACHE_DIR.mkdir(parents=True, exist_ok=True)
DEFAULT_CONFIG_PATH = Path(sys.prefix) / "share" / "empack" / "empack_config.yaml"


def _do_i_own(path: str | Path) -> bool:
"""Verify if the current user has write access to the given path. Sourced from
https://github.com/jupyter/jupyter_core/blob/fa513c1550bbd1ebcc14a4a79eb8c5d95e3e23c9/jupyter_core/paths.py#L75-L99
"""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

# Derived from IPython.utils.path, which is
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

p = Path(path).resolve()

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 Exception: # noqa: S110
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 get_config_path() -> Path:
"""Find the empack configuration file by checking common locations.

This function checks for the config file in the following order:
1. Inside the environment's share directory (conda-style environments)
2. Inside a share/ directory next to a virtual environment

Returns:
Path: Location of the empack_config.yaml file
"""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

# Derived from IPython.utils.path, which is
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.

# 1. Check for config in environment's share directory. This is applicable
# for conda/mamba/micromamba style environments.
prefix = None
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)
):
prefix = Path(os.environ["CONDA_PREFIX"])
else:
prefix = Path(sys.prefix)

config_path = prefix / "share" / "empack" / "empack_config.yaml"
if config_path.exists():
return config_path

# 2. For virtual environments via virtualenv/venv/uv, check if share/ is next
# to the environment base directory. This is also applicable for the case
# where there's no virtual environment at all (--user install).
if sys.prefix != sys.base_prefix and _do_i_own(sys.prefix):
venv_parent = Path(sys.prefix).parent
parent_share = venv_parent / "share" / "empack" / "empack_config.yaml"
if parent_share.exists():
return parent_share


DEFAULT_CONFIG_PATH = get_config_path()


def filename_base_from_meta(pkg_meta):
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ classifiers = [
"Programming Language :: Python :: 3.11",
]
dependencies = [
"appdirs",
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems the CI says appdirs is still being used

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 will be addressed by emscripten-forge/pyjs-code-runner#15, marking for completeness :)

"platformdirs",
"networkx",
"pyyaml",
"requests",
Expand Down
Loading