Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-22.04, ubuntu-latest, macos-14, macos-latest]
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.15"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14", "3.15"]

steps:
- uses: actions/checkout@v7
Expand Down
8 changes: 4 additions & 4 deletions argcomplete/completers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import subprocess
from collections.abc import Callable, Generator, Iterable, Mapping
from shlex import quote
from typing import Final
from typing import Final, Union

_Ignored = object

Expand All @@ -27,14 +27,14 @@

def __call__(
self, *, prefix: str, action: argparse.Action, parser: argparse.ArgumentParser, parsed_args: argparse.Namespace
) -> Iterable[str]:

Check failure on line 30 in argcomplete/completers.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (FA102)

argcomplete/completers.py:30:10: FA102 Missing `from __future__ import annotations`, but uses PEP 585 collection help: Add `from __future__ import annotations`
raise NotImplementedError("This method should be implemented by a subclass.")


class ChoicesCompleter(BaseCompleter):
choices: Final[Mapping[str, str | bytes]]
choices: Final[Mapping[str, Union[str, bytes]]]

Check failure on line 35 in argcomplete/completers.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (FA100)

argcomplete/completers.py:35:33: FA100 Add `from __future__ import annotations` to simplify `typing.Union` help: Add `from __future__ import annotations`

Check failure on line 35 in argcomplete/completers.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (FA102)

argcomplete/completers.py:35:20: FA102 Missing `from __future__ import annotations`, but uses PEP 585 collection help: Add `from __future__ import annotations`

def __init__(self, choices: Mapping[str, str | bytes]) -> None:
def __init__(self, choices: Mapping[str, Union[str, bytes]]) -> None:

Check failure on line 37 in argcomplete/completers.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (FA100)

argcomplete/completers.py:37:46: FA100 Add `from __future__ import annotations` to simplify `typing.Union` help: Add `from __future__ import annotations`

Check failure on line 37 in argcomplete/completers.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (FA102)

argcomplete/completers.py:37:33: FA102 Missing `from __future__ import annotations`, but uses PEP 585 collection help: Add `from __future__ import annotations`
self.choices = choices

def _convert(self, choice):
Expand All @@ -57,7 +57,7 @@
allowednames: Final[list[str]]
directories: Final[bool]

def __init__(self, allowednames: Iterable[str] | str = (), directories: bool = True) -> None:
def __init__(self, allowednames: Union[Iterable[str], str] = (), directories: bool = True) -> None:
# Fix if someone passes in a string instead of a list
if isinstance(allowednames, (str, bytes)):
allowednames = [allowednames]
Expand Down
34 changes: 17 additions & 17 deletions argcomplete/finders.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import os
import sys
from collections.abc import Container, Mapping
from typing import Callable, Literal, TextIO
from typing import Callable, Literal, Optional, TextIO, Union

from . import io as _io
from .completers import BaseCompleter, ChoicesCompleter, FilesCompleter, SuppressCompleter
Expand Down Expand Up @@ -37,10 +37,10 @@ class CompletionFinder:
:meth:`CompletionFinder.__call__()`.
"""

_parser: argparse.ArgumentParser | None
_formatter: argparse.HelpFormatter | None
always_complete_options: bool | Literal["long", "short"]
exclude: Container[str] | None
_parser: Optional[argparse.ArgumentParser]
_formatter: Optional[argparse.HelpFormatter]
always_complete_options: Union[bool, Literal["long", "short"]]
exclude: Optional[Container[str]]
validator: Callable[[str, str], bool]
print_suppressed: bool
completing: bool
Expand All @@ -53,13 +53,13 @@ class CompletionFinder:

def __init__(
self,
argument_parser: argparse.ArgumentParser | None = None,
always_complete_options: bool | Literal["long", "short"] = True,
exclude: Container[str] | None = None,
validator: Callable[[str, str], bool] | None = None,
argument_parser: Optional[argparse.ArgumentParser] = None,
always_complete_options: Union[bool, Literal["long", "short"]] = True,
exclude: Optional[Container[str]] = None,
validator: Optional[Callable[[str, str], bool]] = None,
print_suppressed: bool = False,
default_completer: BaseCompleter = FilesCompleter(),
append_space: bool | None = None,
append_space: Optional[bool] = None,
) -> None:
self._parser = argument_parser # type: ignore[assignment]
self._formatter = None
Expand All @@ -79,13 +79,13 @@ def __init__(
def __call__(
self,
argument_parser: argparse.ArgumentParser,
always_complete_options: bool | str = True,
always_complete_options: Union[bool, str] = True,
exit_method: Callable = os._exit,
output_stream: TextIO | None = None,
exclude: Container[str] | None = None,
validator: Callable[[str, str], bool] | None = None,
output_stream: Optional[TextIO] = None,
exclude: Optional[Container[str]] = None,
validator: Optional[Callable[[str, str], bool]] = None,
print_suppressed: bool = False,
append_space: bool | None = None,
append_space: Optional[bool] = None,
default_completer: BaseCompleter = FilesCompleter(),
) -> None:
"""
Expand Down Expand Up @@ -523,7 +523,7 @@ def filter_completions(self, completions: list[str]) -> list[str]:
return filtered_completions

def quote_completions(
self, completions: list[str], cword_prequote: str, last_wordbreak_pos: int | None
self, completions: list[str], cword_prequote: str, last_wordbreak_pos: Optional[int]
) -> list[str]:
"""
If the word under the cursor started with a quote (as indicated by a nonempty ``cword_prequote``), escapes
Expand Down Expand Up @@ -588,7 +588,7 @@ def quote_completions(

return escaped_completions

def rl_complete(self, text: str, state: int) -> str | None:
def rl_complete(self, text: str, state: int) -> Optional[str]:
"""
Alternate entry point for using the argcomplete completer in a readline-based REPL. See also
`rlcompleter <https://docs.python.org/3/library/rlcompleter.html#completer-objects>`_.
Expand Down
5 changes: 3 additions & 2 deletions argcomplete/lexers.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import os
from typing import Optional

from .exceptions import ArgcompleteException
from .io import debug
from .packages import _shlex


def split_line(line: str, point: int | None = None) -> tuple[str, str, str, list[str], int | None]:
def split_line(line: str, point: Optional[int] = None) -> tuple[str, str, str, list[str], Optional[int]]:
if point is None:
point = len(line)
line = line[:point]
Expand All @@ -14,7 +15,7 @@ def split_line(line: str, point: int | None = None) -> tuple[str, str, str, list
lexer.wordbreaks = os.environ.get("_ARGCOMPLETE_COMP_WORDBREAKS", "")
words = []

def split_word(word: str) -> tuple[str, str, str, list[str], int | None]:
def split_word(word: str) -> tuple[str, str, str, list[str], Optional[int]]:
# TODO: make this less ugly
point_in_word = len(word) + point - lexer.instream.tell()
if isinstance(lexer.state, (str, bytes)) and lexer.state in lexer.whitespace:
Expand Down
5 changes: 3 additions & 2 deletions argcomplete/scripts/activate_global_python_argcomplete.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import site
import subprocess
import sys
from typing import Optional, Union

import argcomplete

Expand Down Expand Up @@ -108,7 +109,7 @@ def get_consent() -> bool:
return False


def append_to_config_file(path: str | os.PathLike[str], shellcode: str) -> None:
def append_to_config_file(path: Union[str, os.PathLike[str]], shellcode: str) -> None:
if os.path.exists(path):
with open(path, 'r') as fh:
if shellcode in fh.read():
Expand All @@ -126,7 +127,7 @@ def append_to_config_file(path: str | os.PathLike[str], shellcode: str) -> None:
print("Added.", file=sys.stderr)


def link_zsh_user_rcfile(zsh_fpath: str | None = None) -> None:
def link_zsh_user_rcfile(zsh_fpath: Optional[str] = None) -> None:
zsh_rcfile = os.path.join(os.path.expanduser(os.environ.get("ZDOTDIR", "~")), ".zshenv")
append_to_config_file(zsh_rcfile, zsh_shellcode.format(zsh_fpath=zsh_fpath or get_activator_dir()))

Expand Down
5 changes: 3 additions & 2 deletions argcomplete/shell_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from collections.abc import Iterable
from shlex import quote
from typing import Optional

bashcode = r"""#compdef %(executables)s
# Run something, muting output or redirecting it to the debug stream
Expand Down Expand Up @@ -140,8 +141,8 @@ def shellcode(
executables: Iterable[str],
use_defaults: bool = True,
shell: str = "bash",
complete_arguments: Iterable[str] | None = None,
argcomplete_script: str | None = None,
complete_arguments: Optional[Iterable[str]] = None,
argcomplete_script: Optional[str] = None,
) -> str:
"""
Provide the shell code required to register a python executable for use with the argcomplete module.
Expand Down
Loading