@@ -2301,6 +2301,12 @@ def state_modulename_name(self, line):
23012301 # modulename.fnname [as c_basename] [-> return annotation]
23022302 # square brackets denote optional syntax.
23032303 #
2304+ # alternatively:
2305+ # modulename.fnname [as c_basename] = modulename.existing_fn_name
2306+ # clones the parameters and return converter from that
2307+ # function. you can't modify them. you must enter a
2308+ # new docstring.
2309+ #
23042310 # (but we might find a directive first!)
23052311 #
23062312 # this line is permitted to start with whitespace.
@@ -2319,6 +2325,45 @@ def state_modulename_name(self, line):
23192325 directive (* fields [1 :])
23202326 return
23212327
2328+ # are we cloning?
2329+ before , equals , existing = line .rpartition ('=' )
2330+ if equals :
2331+ full_name , _ , c_basename = before .partition (' as ' )
2332+ full_name = full_name .strip ()
2333+ c_basename = c_basename .strip ()
2334+ existing = existing .strip ()
2335+ if (is_legal_py_identifier (full_name ) and
2336+ (not c_basename or is_legal_c_identifier (c_basename )) and
2337+ is_legal_py_identifier (existing )):
2338+ # we're cloning!
2339+ fields = [x .strip () for x in existing .split ('.' )]
2340+ function_name = fields .pop ()
2341+ module , cls = self .clinic ._module_and_class (fields )
2342+
2343+ for existing_function in (cls or module ).functions :
2344+ if existing_function .name == function_name :
2345+ break
2346+ else :
2347+ existing_function = None
2348+ if not existing_function :
2349+ fail ("Couldn't find existing function " + repr (existing ) + "!" )
2350+
2351+ fields = [x .strip () for x in full_name .split ('.' )]
2352+ function_name = fields .pop ()
2353+ module , cls = self .clinic ._module_and_class (fields )
2354+
2355+ if not (existing_function .kind == self .kind and existing_function .coexist == self .coexist ):
2356+ fail ("'kind' of function and cloned function don't match! (@classmethod/@staticmethod/@coexist)" )
2357+ self .function = Function (name = function_name , full_name = full_name , module = module , cls = cls , c_basename = c_basename ,
2358+ return_converter = existing_function .return_converter , kind = existing_function .kind , coexist = existing_function .coexist )
2359+
2360+ self .function .parameters = existing_function .parameters .copy ()
2361+
2362+ self .block .signatures .append (self .function )
2363+ (cls or module ).functions .append (self .function )
2364+ self .next (self .state_function_docstring )
2365+ return
2366+
23222367 line , _ , returns = line .partition ('->' )
23232368
23242369 full_name , _ , c_basename = line .partition (' as ' )
@@ -2373,6 +2418,7 @@ def state_modulename_name(self, line):
23732418 self .function = Function (name = function_name , full_name = full_name , module = module , cls = cls , c_basename = c_basename ,
23742419 return_converter = return_converter , kind = self .kind , coexist = self .coexist )
23752420 self .block .signatures .append (self .function )
2421+ (cls or module ).functions .append (self .function )
23762422 self .next (self .state_parameters_start )
23772423
23782424 # Now entering the parameters section. The rules, formally stated:
0 commit comments