@@ -157,44 +157,6 @@ def _is_descriptor(self, member: Any) -> bool:
157157
158158
159159class BaseParser (IParser ):
160- def is_print_safe (self , value : Any ) -> bool :
161- value_type = type (value )
162- # Use exact type match, not `isinstance()` that allows inherited types pass
163- if value is None or value_type in (int , str ):
164- return True
165- if value_type in (float , complex ):
166- try :
167- # checks for NaN, +inf, -inf
168- eval (repr (value ))
169- return True
170- except (SyntaxError , NameError ):
171- return False
172- if value_type in (list , tuple , set ):
173- assert isinstance (value , (list , tuple , set ))
174- for x in value :
175- if not self .is_print_safe (x ):
176- return False
177- return True
178- if value_type is dict :
179- assert isinstance (value , dict )
180- for k , v in value .items ():
181- if not self .is_print_safe (k ) or not self .is_print_safe (v ):
182- return False
183- return True
184- if inspect .isfunction (value ):
185- module_name = getattr (value , "__module__" , None )
186- qual_name = getattr (value , "__qualname__" , None )
187- if (
188- module_name is not None
189- and "<" not in module_name
190- and qual_name is not None
191- and "<" not in qual_name
192- ):
193- return True
194- if inspect .ismodule (value ):
195- return True
196- return False
197-
198160 def handle_alias (self , path : QualifiedName , origin : Any ) -> Alias | None :
199161 full_name = self ._get_full_name (path , origin )
200162 if full_name is None :
@@ -345,10 +307,67 @@ def handle_method(self, path: QualifiedName, method: Any) -> list[Method]:
345307 ]
346308
347309 def handle_value (self , value : Any ) -> Value :
348- result = self .parse_value_str (self .value_to_repr (value ))
349- if self .is_print_safe (value ):
350- result .is_print_safe = True
351- return result
310+ value_type = type (value )
311+ # Use exact type match, not `isinstance()` that allows inherited types pass
312+ if value is None or value_type in (bool , int , str ):
313+ return Value (repr = repr (value ), is_print_safe = True )
314+ if value_type in (float , complex ):
315+ try :
316+ # checks for NaN, +inf, -inf
317+ repr_str = repr (value )
318+ eval (repr_str )
319+ return Value (repr = repr_str , is_print_safe = True )
320+ except (SyntaxError , NameError ):
321+ pass
322+ if value_type in (list , tuple , set ):
323+ assert isinstance (value , (list , tuple , set ))
324+ if len (value ) == 0 :
325+ return Value (repr = f"{ value_type .__name__ } ()" , is_print_safe = True )
326+ elements : list [Value ] = [self .handle_value (el ) for el in value ]
327+ is_print_safe = all (el .is_print_safe for el in elements )
328+ left , right = {
329+ list : "[]" ,
330+ tuple : "()" ,
331+ set : "{}" ,
332+ }[value_type ]
333+ return Value (
334+ repr = "" .join ([left , ", " .join (el .repr for el in elements ), right ]),
335+ is_print_safe = is_print_safe ,
336+ )
337+ if value_type is dict :
338+ assert isinstance (value , dict )
339+ parts = []
340+ is_print_safe = True
341+ for k , v in value .items ():
342+ k_value = self .handle_value (k )
343+ v_value = self .handle_value (v )
344+ parts .append (f"{ k_value .repr } : { v_value .repr } " )
345+ is_print_safe = (
346+ is_print_safe and k_value .is_print_safe and v_value .is_print_safe
347+ )
348+
349+ return Value (
350+ repr = "" .join (["{" , ", " .join (parts ), "}" ]), is_print_safe = is_print_safe
351+ )
352+ if inspect .isroutine (value ):
353+ module_name = getattr (value , "__module__" , None )
354+ qual_name = getattr (value , "__qualname__" , None )
355+ if (
356+ module_name is not None
357+ and "<" not in module_name
358+ and qual_name is not None
359+ and "<" not in qual_name
360+ ):
361+ if module_name == "builtins" :
362+ repr_str = qual_name
363+ else :
364+ repr_str = f"{ module_name } .{ qual_name } "
365+ return Value (repr = repr_str , is_print_safe = True )
366+ if inspect .isclass (value ):
367+ return Value (repr = str (self .handle_type (value )), is_print_safe = True )
368+ if inspect .ismodule (value ):
369+ return Value (repr = value .__name__ , is_print_safe = True )
370+ return Value (repr = repr (value ), is_print_safe = False )
352371
353372 def handle_type (self , type_ : type ) -> QualifiedName :
354373 return QualifiedName (
@@ -364,22 +383,6 @@ def handle_type(self, type_: type) -> QualifiedName:
364383 def parse_value_str (self , value : str ) -> Value :
365384 return Value (value )
366385
367- def value_to_repr (self , value : Any ) -> str :
368- if inspect .ismodule (value ):
369- return value .__name__
370- if inspect .isroutine (value ):
371- parts = []
372- module = getattr (value , "__module__" , None )
373- if module is not None :
374- parts .append (module )
375- name = getattr (value , "__qualname__" , None )
376- if name is not None :
377- parts .append (name )
378- return "." .join (parts )
379- if value is ...:
380- return "..."
381- return repr (value )
382-
383386 def report_error (self , error : ParserError ):
384387 if isinstance (error , NameResolutionError ):
385388 if error .name [0 ] == "module" :
0 commit comments