11import inspect
2+ import typing as t
23from functools import update_wrapper
34
45from .core import Argument
89from .globals import get_current_context
910from .utils import echo
1011
12+ if t .TYPE_CHECKING :
13+ F = t .TypeVar ("F" , bound = t .Callable [..., t .Any ])
1114
12- def pass_context (f ):
15+
16+ def pass_context (f : "F" ) -> "F" :
1317 """Marks a callback as wanting to receive the current context
1418 object as first argument.
1519 """
1620
1721 def new_func (* args , ** kwargs ):
1822 return f (get_current_context (), * args , ** kwargs )
1923
20- return update_wrapper (new_func , f )
24+ return update_wrapper (t . cast ( "F" , new_func ) , f )
2125
2226
23- def pass_obj (f ) :
27+ def pass_obj (f : "F" ) -> "F" :
2428 """Similar to :func:`pass_context`, but only pass the object on the
2529 context onwards (:attr:`Context.obj`). This is useful if that object
2630 represents the state of a nested system.
@@ -29,10 +33,12 @@ def pass_obj(f):
2933 def new_func (* args , ** kwargs ):
3034 return f (get_current_context ().obj , * args , ** kwargs )
3135
32- return update_wrapper (new_func , f )
36+ return update_wrapper (t . cast ( "F" , new_func ) , f )
3337
3438
35- def make_pass_decorator (object_type , ensure = False ):
39+ def make_pass_decorator (
40+ object_type : t .Type , ensure : bool = False
41+ ) -> "t.Callable[[F], F]" :
3642 """Given an object type this creates a decorator that will work
3743 similar to :func:`pass_obj` but instead of passing the object of the
3844 current context, it will find the innermost context of type
@@ -55,23 +61,59 @@ def new_func(ctx, *args, **kwargs):
5561 remembered on the context if it's not there yet.
5662 """
5763
58- def decorator (f ) :
64+ def decorator (f : "F" ) -> "F" :
5965 def new_func (* args , ** kwargs ):
6066 ctx = get_current_context ()
67+
6168 if ensure :
6269 obj = ctx .ensure_object (object_type )
6370 else :
6471 obj = ctx .find_object (object_type )
72+
6573 if obj is None :
6674 raise RuntimeError (
6775 "Managed to invoke callback without a context"
6876 f" object of type { object_type .__name__ !r} "
6977 " existing."
7078 )
79+
7180 return ctx .invoke (f , obj , * args , ** kwargs )
7281
73- return update_wrapper (new_func , f )
82+ return update_wrapper (t .cast ("F" , new_func ), f )
83+
84+ return decorator
85+
86+
87+ def pass_meta_key (
88+ key : str , * , doc_description : t .Optional [str ] = None
89+ ) -> "t.Callable[[F], F]" :
90+ """Create a decorator that passes a key from
91+ :attr:`click.Context.meta` as the first argument to the decorated
92+ function.
93+
94+ :param key: Key in ``Context.meta`` to pass.
95+ :param doc_description: Description of the object being passed,
96+ inserted into the decorator's docstring. Defaults to "the 'key'
97+ key from Context.meta".
7498
99+ .. versionadded:: 8.0
100+ """
101+
102+ def decorator (f : "F" ) -> "F" :
103+ def new_func (* args , ** kwargs ):
104+ ctx = get_current_context ()
105+ obj = ctx .meta [key ]
106+ return ctx .invoke (f , obj , * args , ** kwargs )
107+
108+ return update_wrapper (t .cast ("F" , new_func ), f )
109+
110+ if doc_description is None :
111+ doc_description = f"the { key !r} key from :attr:`click.Context.meta`"
112+
113+ decorator .__doc__ = (
114+ f"Decorator that passes { doc_description } as the first argument"
115+ " to the decorated function."
116+ )
75117 return decorator
76118
77119
0 commit comments