@@ -185,13 +185,9 @@ def _patch_click_types(
185185        hint : typing .Type [Any ]
186186        _ , hint  =  _strip_optional (type_hints [key ])
187187        if  "type"  not  in   annotation .kwargs :
188-             stub : click .core .Option  |  click .core .Argument 
189-             if  annotation .callable  is  click .option :
190-                 stub  =  click .core .Option (annotation .args , ** annotation .kwargs )
191-                 if  stub .is_flag :
192-                     continue 
193-             else :
194-                 stub  =  click .core .Argument (annotation .args , ** annotation .kwargs )
188+             stub  =  _build_stub (annotation )
189+             if  hasattr (stub , "is_flag" ) and  stub .is_flag :
190+                 continue 
195191            annotation .kwargs ["type" ] =  _eval_type (key , hint , stub , complete_type_inferences )
196192
197193
@@ -218,6 +214,23 @@ def _eval_type(
218214    raise  TypeError (f"Could not infer ParamType for { key }   type { hint !r}  . Explicitly annotate type=<type>" )
219215
220216
217+ def  _build_stub (annotation : _DelayedCall ) ->  click .core .Option  |  click .core .Argument :
218+     """Stub uses click's parser rather than trying to second guess how click will behave.""" 
219+     if  "cls"  in  annotation .kwargs :
220+         return  annotation .kwargs ["cls" ](
221+             annotation .args ,
222+             ** {k : v 
223+                for  k , v  in  annotation .kwargs .items () if  k  !=  "cls" },
224+         )
225+ 
226+     if  annotation .callable  is  click .option :
227+         return  click .core .Option (annotation .args , ** annotation .kwargs )
228+     elif  annotation .callable  is  click .argument :
229+         return  click .core .Argument (annotation .args , ** annotation .kwargs )
230+ 
231+     raise  TypeError (f"Unknown annotation callable { annotation .callable !r}  " )
232+ 
233+ 
221234def  _patch_required (arg_class : typing .Type [Arg ], annotations : dict [str , _DelayedCall ]) ->  None :
222235    """Default click option to required if typehint is not OPTIONAL 
223236
@@ -228,15 +241,15 @@ def _patch_required(arg_class: typing.Type[Arg], annotations: dict[str, _Delayed
228241    :return: None, annotations are updated in place""" 
229242    type_hints  =  typing .get_type_hints (arg_class )
230243    for  key , annotation  in  annotations .items ():
231-         hint : typing .Type [Any ]
232-         is_optional , hint  =  _strip_optional (type_hints [key ])
244+         is_optional , _  =  _strip_optional (type_hints [key ])
233245        if  not  is_optional :
234246            if  annotation .callable  is  click .option :
235247                # If required or default set directly. 
236248                if  "required"  not  in   annotation .kwargs  and  "default"  not  in   annotation .kwargs :
237-                     # Stub uses click's parser rather than trying to second guess how click will behave 
249+                     stub  =  _build_stub (annotation )
250+                     if  not  isinstance (stub , click .core .Option ):
251+                         raise  TypeError (f"Expected click.core.Option or its subclass, got { stub !r}  " )
238252                    # If click would imply is_flag or multiple 
239-                     stub  =  click .core .Option (annotation .args , ** annotation .kwargs )
240253                    if  not  stub .is_flag  and  not  stub .multiple :
241254                        annotation .kwargs ["required" ] =  True 
242255
0 commit comments