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

Fix nushell #922

Merged
merged 4 commits into from
Aug 25, 2023
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: 5 additions & 1 deletion src/hatch/env/plugin/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
from abc import ABC, abstractmethod
from contextlib import contextmanager
from os.path import isabs
from typing import TYPE_CHECKING

from hatch.config.constants import AppEnvVars
from hatch.env.utils import add_verbosity_flag
from hatch.project.utils import format_script_commands, parse_script_command
from hatch.utils.structures import EnvVars

if TYPE_CHECKING:
from collections.abc import Iterable


class EnvironmentInterface(ABC):
"""
Expand Down Expand Up @@ -756,7 +760,7 @@ def build_environment_exists(self):
"""
return False

def enter_shell(self, name, path, args):
def enter_shell(self, name: str, path: str, args: Iterable[str]):
"""
Spawn a [shell](../../config/hatch.md#shell) within the environment.

Expand Down
8 changes: 7 additions & 1 deletion src/hatch/env/virtual.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
from __future__ import annotations

from base64 import urlsafe_b64encode
from contextlib import contextmanager, suppress
from hashlib import sha256
from os.path import isabs
from typing import TYPE_CHECKING

from hatch.env.plugin.interface import EnvironmentInterface
from hatch.utils.fs import Path
from hatch.utils.shells import ShellManager
from hatch.venv.core import VirtualEnv

if TYPE_CHECKING:
from collections.abc import Iterable


class VirtualEnvironment(EnvironmentInterface):
PLUGIN_NAME = 'virtual'
Expand Down Expand Up @@ -141,7 +147,7 @@ def command_context(self):
with self.safe_activation():
yield

def enter_shell(self, name, path, args):
def enter_shell(self, name: str, path: str, args: Iterable[str]):
shell_executor = getattr(self.shells, f'enter_{name}', None)
if shell_executor is None:
# Manually activate in lieu of an activation script
Expand Down
34 changes: 18 additions & 16 deletions src/hatch/utils/shells.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from __future__ import annotations

import sys
from typing import TYPE_CHECKING, Callable
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from collections.abc import Callable, Iterable
flying-sheep marked this conversation as resolved.
Show resolved Hide resolved
from types import FrameType

from hatch.env.plugin.interface import EnvironmentInterface
Expand All @@ -14,10 +15,10 @@ class ShellManager:
def __init__(self, environment: EnvironmentInterface) -> None:
self.environment = environment

def enter_cmd(self, path: str, args: list[str], exe_dir: Path) -> None:
def enter_cmd(self, path: str, args: Iterable[str], exe_dir: Path) -> None:
self.environment.platform.exit_with_command([path or 'cmd', '/k', str(exe_dir / 'activate.bat')])

def enter_powershell(self, path: str, args: list[str], exe_dir: Path) -> None:
def enter_powershell(self, path: str, args: Iterable[str], exe_dir: Path) -> None:
self.environment.platform.exit_with_command(
[
path or 'powershell',
Expand All @@ -30,10 +31,10 @@ def enter_powershell(self, path: str, args: list[str], exe_dir: Path) -> None:
]
)

def enter_pwsh(self, path: str, args: list[str], exe_dir: Path) -> None:
def enter_pwsh(self, path: str, args: Iterable[str], exe_dir: Path) -> None:
self.enter_powershell(path or 'pwsh', args, exe_dir)

def enter_xonsh(self, path: str, args: list[str], exe_dir: Path) -> None:
def enter_xonsh(self, path: str, args: Iterable[str], exe_dir: Path) -> None:
if self.environment.platform.windows:
with self.environment:
self.environment.platform.exit_with_command(
Expand All @@ -47,45 +48,45 @@ def enter_xonsh(self, path: str, args: list[str], exe_dir: Path) -> None:
callback=lambda terminal: terminal.sendline(f'$PATH.insert(0, {str(exe_dir)!r})'),
)

def enter_bash(self, path: str, args: list[str], exe_dir: Path) -> None:
def enter_bash(self, path: str, args: Iterable[str], exe_dir: Path) -> None:
if self.environment.platform.windows:
self.environment.platform.exit_with_command(
[path or 'bash', '--init-file', exe_dir / 'activate', *(args or ['-i'])]
)
else:
self.spawn_linux_shell(path or 'bash', args or ['-i'], script=exe_dir / 'activate')

def enter_fish(self, path: str, args: list[str], exe_dir: Path) -> None:
def enter_fish(self, path: str, args: Iterable[str], exe_dir: Path) -> None:
self.spawn_linux_shell(path or 'fish', args or ['-i'], script=exe_dir / 'activate.fish')

def enter_zsh(self, path: str, args: list[str], exe_dir: Path) -> None:
def enter_zsh(self, path: str, args: Iterable[str], exe_dir: Path) -> None:
self.spawn_linux_shell(path or 'zsh', args or ['-i'], script=exe_dir / 'activate')

def enter_ash(self, path: str, args: list[str], exe_dir: Path) -> None:
def enter_ash(self, path: str, args: Iterable[str], exe_dir: Path) -> None:
self.spawn_linux_shell(path or 'ash', args or ['-i'], script=exe_dir / 'activate')

def enter_nu(self, path: str, args: list[str], exe_dir: Path) -> None:
def enter_nu(self, path: str, args: Iterable[str], exe_dir: Path) -> None:
executable = path or 'nu'
activation_script = exe_dir / 'activate.nu'
if self.environment.platform.windows:
self.environment.platform.exit_with_command(
[executable, '-c', f'source "{activation_script}"; "{executable}"']
)
else:
self.spawn_linux_shell(executable, args or None, script=activation_script)
self.spawn_linux_shell(executable, args, script=activation_script)

def enter_tcsh(self, path: str, args: list[str], exe_dir: Path) -> None:
def enter_tcsh(self, path: str, args: Iterable[str], exe_dir: Path) -> None:
self.spawn_linux_shell(path or 'tcsh', args or ['-i'], script=exe_dir / 'activate.csh')

def enter_csh(self, path: str, args: list[str], exe_dir: Path) -> None:
def enter_csh(self, path: str, args: Iterable[str], exe_dir: Path) -> None:
self.spawn_linux_shell(path or 'csh', args or ['-i'], script=exe_dir / 'activate.csh')

if sys.platform == 'win32':

def spawn_linux_shell(
self,
path: str,
args: list[str] | None = None,
args: Iterable[str] | None = None,
*,
script: Path | None = None,
callback: Callable | None = None,
Expand All @@ -97,7 +98,7 @@ def spawn_linux_shell(
def spawn_linux_shell(
self,
path: str,
args: list[str] | None = None,
args: Iterable[str] | None = None,
*,
script: Path | None = None,
callback: Callable | None = None,
Expand All @@ -108,7 +109,8 @@ def spawn_linux_shell(
import pexpect

columns, lines = shutil.get_terminal_size()
terminal = pexpect.spawn(path, args=args, dimensions=(lines, columns))
# pexpect only accepts lists
terminal = pexpect.spawn(path, args=list(args or ()), dimensions=(lines, columns))

def sigwinch_passthrough(sig: int, data: FrameType | None) -> None:
new_columns, new_lines = shutil.get_terminal_size()
Expand Down