@@ -176,18 +176,27 @@ def visit_call(self, node: nodes.Call) -> str:
176176 args .extend (keywords )
177177 return f"{ expr_str } ({ ', ' .join (args )} )"
178178
179+ def _handle_type_params (
180+ self , type_params : list [nodes .TypeVar | nodes .ParamSpec | nodes .TypeVarTuple ]
181+ ) -> str :
182+ return (
183+ f"[{ ', ' .join (tp .accept (self ) for tp in type_params )} ]"
184+ if type_params
185+ else ""
186+ )
187+
179188 def visit_classdef (self , node : nodes .ClassDef ) -> str :
180189 """return an astroid.ClassDef node as string"""
181190 decorate = node .decorators .accept (self ) if node .decorators else ""
191+ type_params = self ._handle_type_params (node .type_params )
182192 args = [n .accept (self ) for n in node .bases ]
183193 if node ._metaclass and not node .has_metaclass_hack ():
184194 args .append ("metaclass=" + node ._metaclass .accept (self ))
185195 args += [n .accept (self ) for n in node .keywords ]
186196 args_str = f"({ ', ' .join (args )} )" if args else ""
187197 docs = self ._docs_dedent (node .doc_node )
188- # TODO: handle type_params
189- return "\n \n {}class {}{}:{}\n {}\n " .format (
190- decorate , node .name , args_str , docs , self ._stmt_list (node .body )
198+ return "\n \n {}class {}{}{}:{}\n {}\n " .format (
199+ decorate , node .name , type_params , args_str , docs , self ._stmt_list (node .body )
191200 )
192201
193202 def visit_compare (self , node : nodes .Compare ) -> str :
@@ -336,17 +345,18 @@ def visit_formattedvalue(self, node: nodes.FormattedValue) -> str:
336345 def handle_functiondef (self , node : nodes .FunctionDef , keyword : str ) -> str :
337346 """return a (possibly async) function definition node as string"""
338347 decorate = node .decorators .accept (self ) if node .decorators else ""
348+ type_params = self ._handle_type_params (node .type_params )
339349 docs = self ._docs_dedent (node .doc_node )
340350 trailer = ":"
341351 if node .returns :
342352 return_annotation = " -> " + node .returns .as_string ()
343353 trailer = return_annotation + ":"
344- # TODO: handle type_params
345- def_format = "\n %s%s %s(%s)%s%s\n %s"
354+ def_format = "\n %s%s %s%s(%s)%s%s\n %s"
346355 return def_format % (
347356 decorate ,
348357 keyword ,
349358 node .name ,
359+ type_params ,
350360 node .args .accept (self ),
351361 trailer ,
352362 docs ,
@@ -455,7 +465,10 @@ def visit_nonlocal(self, node: nodes.Nonlocal) -> str:
455465
456466 def visit_paramspec (self , node : nodes .ParamSpec ) -> str :
457467 """return an astroid.ParamSpec node as string"""
458- return node .name .accept (self )
468+ default_value_str = (
469+ f" = { node .default_value .accept (self )} " if node .default_value else ""
470+ )
471+ return f"**{ node .name .accept (self )} { default_value_str } "
459472
460473 def visit_pass (self , node : nodes .Pass ) -> str :
461474 """return an astroid.Pass node as string"""
@@ -545,15 +558,23 @@ def visit_tuple(self, node: nodes.Tuple) -> str:
545558
546559 def visit_typealias (self , node : nodes .TypeAlias ) -> str :
547560 """return an astroid.TypeAlias node as string"""
548- return node .name .accept (self ) if node .name else "_"
561+ type_params = self ._handle_type_params (node .type_params )
562+ return f"type { node .name .accept (self )} { type_params } = { node .value .accept (self )} "
549563
550564 def visit_typevar (self , node : nodes .TypeVar ) -> str :
551565 """return an astroid.TypeVar node as string"""
552- return node .name .accept (self ) if node .name else "_"
566+ bound_str = f": { node .bound .accept (self )} " if node .bound else ""
567+ default_value_str = (
568+ f" = { node .default_value .accept (self )} " if node .default_value else ""
569+ )
570+ return f"{ node .name .accept (self )} { bound_str } { default_value_str } "
553571
554572 def visit_typevartuple (self , node : nodes .TypeVarTuple ) -> str :
555573 """return an astroid.TypeVarTuple node as string"""
556- return "*" + node .name .accept (self ) if node .name else ""
574+ default_value_str = (
575+ f" = { node .default_value .accept (self )} " if node .default_value else ""
576+ )
577+ return f"*{ node .name .accept (self )} { default_value_str } "
557578
558579 def visit_unaryop (self , node : nodes .UnaryOp ) -> str :
559580 """return an astroid.UnaryOp node as string"""
0 commit comments