Skip to content

Commit

Permalink
Fix nushell (#922)
Browse files Browse the repository at this point in the history
* Fix nushell

* conditional import 1

* conditional import 2
  • Loading branch information
flying-sheep authored Aug 25, 2023
1 parent 4ddbf0a commit 369d7c7
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 18 deletions.
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
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

0 comments on commit 369d7c7

Please sign in to comment.