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
5 changes: 2 additions & 3 deletions src/sh/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
from locale import getpreferredencoding
from queue import Empty, Queue
from shlex import quote as shlex_quote
from types import GeneratorType, ModuleType
from types import GeneratorType, GenericAlias, ModuleType
from typing import Any, Dict, Type, Union

__project_url__ = "https://github.com/amoffat/sh"
Expand Down Expand Up @@ -1466,8 +1466,7 @@ def __repr__(self):

# Allow subscripting at runtime (e.g. Command[RunningCommand]) so that
# type annotations and cast() calls work without a TypeError.
def __class_getitem__(cls, item):
return cls
__class_getitem__ = classmethod(GenericAlias)

def __enter__(self):
self(_with=True)
Expand Down
19 changes: 16 additions & 3 deletions src/sh/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ mechanism that tells type checkers about this dynamic resolution, enabling
patterns like ``from sh import ls`` to type-check cleanly.
"""

import _thread
import threading
from collections.abc import AsyncIterator, Callable, Generator, Iterable, Set
from contextlib import contextmanager
from queue import Queue
from types import GenericAlias, TracebackType
from typing import Any, ClassVar, Generic, IO, Literal, TypeAlias, overload

from typing_extensions import TypeVar
Expand Down Expand Up @@ -545,7 +547,12 @@ class RunningCommand(str):
_ReturnT_co = TypeVar("_ReturnT_co", RunningCommand, str, covariant=True, default=str)

class Command(Generic[_ReturnT_co]):
def __init__(self, name: str, search_paths: list[str] | None = ...) -> None: ...
thread_local: ClassVar[_thread._local] = ...
RunningCommandCls: ClassVar[type[RunningCommand]] = ...

@classmethod
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
def __init__(self, path: str, search_paths: list[str] | None = ...) -> None: ...

# -----------------------------------------------------------------------
# bake() overloads
Expand Down Expand Up @@ -1297,9 +1304,15 @@ class Command(Generic[_ReturnT_co]):
def __repr__(self) -> str: ...
def __eq__(self, other: object) -> bool: ...
def __enter__(self) -> None: ...
def __exit__(self, *args: Any) -> None: ...
def __exit__(
self,
exc_type: type[BaseException] | None,
exc_val: BaseException | None,
exc_tb: TracebackType | None,
) -> None: ...

# sub-command access (e.g. git.log, docker.container.ls)
def __getattr__(self, name: str) -> Command[_ReturnT_co]: ...
def __getattribute__(self, name: str) -> Command[_ReturnT_co]: ...

# ---------------------------------------------------------------------------
# StreamBufferer — exposed via allowlist
Expand Down
Loading