Coverage for typer/completion.py: 100%
65 statements
« prev ^ index » next coverage.py v7.6.1, created at 2025-12-19 20:29 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2025-12-19 20:29 +0000
1import os 1abcdefghi
2import sys 1abcdefghi
3from typing import Any, MutableMapping, Tuple 1abcdefghi
5import click 1abcdefghi
7from ._completion_classes import completion_init 1abcdefghi
8from ._completion_shared import Shells, _get_shell_name, get_completion_script, install 1abcdefghi
9from .core import HAS_SHELLINGHAM 1abcdefghi
10from .models import ParamMeta 1abcdefghi
11from .params import Option 1abcdefghi
12from .utils import get_params_from_function 1abcdefghi
14_click_patched = False 1abcdefghi
17def get_completion_inspect_parameters() -> Tuple[ParamMeta, ParamMeta]: 1abcdefghi
18 completion_init() 1abcdefghi
19 test_disable_detection = os.getenv("_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION") 1abcdefghi
20 if HAS_SHELLINGHAM and not test_disable_detection: 1abcdefghi
21 parameters = get_params_from_function(_install_completion_placeholder_function) 1abcdefghi
22 else:
23 parameters = get_params_from_function( 1abcdefghi
24 _install_completion_no_auto_placeholder_function
25 )
26 install_param, show_param = parameters.values() 1abcdefghi
27 return install_param, show_param 1abcdefghi
30def install_callback(ctx: click.Context, param: click.Parameter, value: Any) -> Any: 1abcdefghi
31 if not value or ctx.resilient_parsing: 1abcdefghi
32 return value # pragma: no cover 1abcdefghi
33 if isinstance(value, str): 1abcdefghi
34 shell, path = install(shell=value) 1abcdefghi
35 else:
36 shell, path = install() 1abcdefghi
37 click.secho(f"{shell} completion installed in {path}", fg="green") 1abcdefghi
38 click.echo("Completion will take effect once you restart the terminal") 1abcdefghi
39 sys.exit(0) 1abcdefghi
42def show_callback(ctx: click.Context, param: click.Parameter, value: Any) -> Any: 1abcdefghi
43 if not value or ctx.resilient_parsing: 1abcdefghi
44 return value # pragma: no cover 1abcdefghi
45 prog_name = ctx.find_root().info_name 1abcdefghi
46 assert prog_name 1abcdefghi
47 complete_var = "_{}_COMPLETE".format(prog_name.replace("-", "_").upper()) 1abcdefghi
48 shell = "" 1abcdefghi
49 test_disable_detection = os.getenv("_TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION") 1abcdefghi
50 if isinstance(value, str): 1abcdefghi
51 shell = value 1abcdefghi
52 elif not test_disable_detection: 1abcdefghi
53 detected_shell = _get_shell_name() 1abcdefghi
54 if detected_shell is not None: 1abcdefghi
55 shell = detected_shell 1abcdefghi
56 script_content = get_completion_script( 1abcdefghi
57 prog_name=prog_name, complete_var=complete_var, shell=shell
58 )
59 click.echo(script_content) 1abcdefghi
60 sys.exit(0) 1abcdefghi
63# Create a fake command function to extract the completion parameters
64def _install_completion_placeholder_function( 1abcdefghi
65 install_completion: bool = Option(
66 None,
67 "--install-completion",
68 callback=install_callback,
69 expose_value=False,
70 help="Install completion for the current shell.",
71 ),
72 show_completion: bool = Option(
73 None,
74 "--show-completion",
75 callback=show_callback,
76 expose_value=False,
77 help="Show completion for the current shell, to copy it or customize the installation.",
78 ),
79) -> Any:
80 pass # pragma: no cover
83def _install_completion_no_auto_placeholder_function( 1abcdefghi
84 install_completion: Shells = Option(
85 None,
86 callback=install_callback,
87 expose_value=False,
88 help="Install completion for the specified shell.",
89 ),
90 show_completion: Shells = Option(
91 None,
92 callback=show_callback,
93 expose_value=False,
94 help="Show completion for the specified shell, to copy it or customize the installation.",
95 ),
96) -> Any:
97 pass # pragma: no cover
100# Re-implement Click's shell_complete to add error message with:
101# Invalid completion instruction
102# To use 7.x instruction style for compatibility
103# And to add extra error messages, for compatibility with Typer in previous versions
104# This is only called in new Command method, only used by Click 8.x+
105def shell_complete( 1abcdefghi
106 cli: click.Command,
107 ctx_args: MutableMapping[str, Any],
108 prog_name: str,
109 complete_var: str,
110 instruction: str,
111) -> int:
112 import click 1abcdefghi
113 import click.shell_completion 1abcdefghi
115 if "_" not in instruction: 1abcdefghi
116 click.echo("Invalid completion instruction.", err=True) 1abcdefghi
117 return 1 1abcdefghi
119 # Click 8 changed the order/style of shell instructions from e.g.
120 # source_bash to bash_source
121 # Typer override to preserve the old style for compatibility
122 # Original in Click 8.x commented:
123 # shell, _, instruction = instruction.partition("_")
124 instruction, _, shell = instruction.partition("_") 1abcdefghi
125 # Typer override end
127 comp_cls = click.shell_completion.get_completion_class(shell) 1abcdefghi
129 if comp_cls is None: 1abcdefghi
130 click.echo(f"Shell {shell} not supported.", err=True) 1abcdefghi
131 return 1 1abcdefghi
133 comp = comp_cls(cli, ctx_args, prog_name, complete_var) 1abcdefghi
135 if instruction == "source": 1abcdefghi
136 click.echo(comp.source()) 1abcdefghi
137 return 0 1abcdefghi
139 # Typer override to print the completion help msg with Rich
140 if instruction == "complete": 1abcdefghi
141 click.echo(comp.complete()) 1abcdefghi
142 return 0 1abcdefghi
143 # Typer override end
145 click.echo(f'Completion instruction "{instruction}" not supported.', err=True) 1abcdefghi
146 return 1 1abcdefghi