Skip to content

Commit

Permalink
Add ~/.local/bin to PATH in the current shell session (#41)
Browse files Browse the repository at this point in the history
  • Loading branch information
volod-vana authored Nov 11, 2024
1 parent 92745d4 commit 4a52d31
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 3 deletions.
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "vana"
version = "0.24.0"
version = "0.25.0"
description = ""
authors = ["Tim Nunamaker <[email protected]>", "Volodymyr Isai <[email protected]>", "Kahtaf Alam <[email protected]>"]
readme = "README.md"
Expand Down Expand Up @@ -31,7 +31,7 @@ tomli = "^2.1.0"


[build-system]
requires = ["poetry-core", "setuptools>=42", "wheel"]
requires = ["poetry-core", "setuptools>=42", "wheel", "tomli>=2.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.poetry.scripts]
Expand Down
24 changes: 24 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
from setuptools import setup, find_packages
from setuptools.command.install import install
from distutils.cmd import Command
from typing import Dict, Type, cast
import tomli
import subprocess
import sys

with open("pyproject.toml", "rb") as f:
pyproject = tomli.load(f)
Expand All @@ -13,6 +18,24 @@
if pkg != "python"
]


class PostInstallCommand(install):
"""Custom command that runs PATH setup after installation"""

def run(self) -> None:
"""Run install and then update PATH"""
install.run(self)
try:
# Run vanacli with post-install flag
subprocess.run([sys.executable, "-m", "vana.cli", "--post-install"], check=True)
except subprocess.CalledProcessError:
print("Warning: Failed to update PATH configuration", file=sys.stderr)


command_classes = cast(Dict[str, Type[Command]], {
'install': PostInstallCommand
})

setup(
name="vana",
version=version,
Expand All @@ -24,4 +47,5 @@
],
},
python_requires=pyproject["tool"]["poetry"]["dependencies"]["python"],
cmdclass=command_classes
)
2 changes: 1 addition & 1 deletion vana/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.

__version__ = "0.24.0"
__version__ = "0.25.0"

import rich

Expand Down
50 changes: 50 additions & 0 deletions vana/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import argparse
import shtab
import sys
import os
from pathlib import Path
import vana
from importlib.metadata import entry_points
from typing import List, Optional
Expand Down Expand Up @@ -119,6 +121,39 @@
}


def ensure_local_bin_in_path():
"""Ensures ~/.local/bin is in PATH for the current session"""
local_bin = str(Path.home() / ".local" / "bin")
if local_bin not in os.environ.get("PATH", "").split(os.pathsep):
os.environ["PATH"] = local_bin + os.pathsep + os.environ.get("PATH", "")


def update_shell_config():
"""Updates shell config to include ~/.local/bin in PATH"""
local_bin = str(Path.home() / ".local" / "bin")

# Check if already in PATH
if local_bin in os.environ.get("PATH", "").split(os.pathsep):
return

# Determine shell config file
shell = os.environ.get("SHELL", "")
home = str(Path.home())

if "zsh" in shell:
rc_file = os.path.join(home, ".zshrc")
else: # default to bash
rc_file = os.path.join(home, ".bashrc")

if os.path.exists(rc_file):
with open(rc_file, 'r') as f:
content = f.read()

if "PATH=\"$HOME/.local/bin:$PATH\"" not in content:
with open(rc_file, 'a') as f:
f.write('\n# Added by vana installation\nexport PATH="$HOME/.local/bin:$PATH"\n')


def load_external_commands():
"""
Load external commands from entry points.
Expand All @@ -133,6 +168,7 @@ def load_external_commands():
except Exception as e:
pass


class CLIErrorParser(argparse.ArgumentParser):
"""
Custom ArgumentParser for better error messages.
Expand Down Expand Up @@ -185,6 +221,9 @@ def __init__(
# Check if the config is valid.
cli.check_config(self.config)

# Ensure ~/.local/bin is in PATH
ensure_local_bin_in_path()

# If no_version_checking is not set or set as False in the config, version checking is done.
if not self.config.get("no_version_checking", d=True):
try:
Expand Down Expand Up @@ -215,6 +254,11 @@ def __create_parser__() -> "argparse.ArgumentParser":
choices=shtab.SUPPORTED_SHELLS,
help="Print shell tab completion script",
)
parser.add_argument(
"--post-install",
action="store_true",
help=argparse.SUPPRESS, # Hide from help output
)
# Add arguments for each sub-command.
cmd_parsers = parser.add_subparsers(dest="command")
# Add argument parsers for all available commands.
Expand Down Expand Up @@ -319,6 +363,12 @@ def main():
parser = cli.__create_parser__()
args, unknown = parser.parse_known_args()

# Handle post-install PATH setup
if getattr(args, 'post_install', False):
update_shell_config()
ensure_local_bin_in_path()
return

if args.print_completion: # Check for print-completion argument
print(shtab.complete(parser, args.print_completion))
return
Expand Down

0 comments on commit 4a52d31

Please sign in to comment.