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