19
19
import functools
20
20
import inspect
21
21
22
- from typing import Any , Dict , List , Optional , Tuple
22
+ from typing import Any , Dict , List , Optional , NamedTuple , Tuple
23
23
24
24
from tensorflow_docs .api_generator import obj_type as obj_type_lib
25
25
@@ -291,7 +291,14 @@ class or module.
291
291
292
292
return children
293
293
294
- def _score_name (self , name : str ):
294
+ class NameScore (NamedTuple ):
295
+ defining_class_score : int
296
+ experimental_score : int
297
+ keras_score : int
298
+ module_length_score : int
299
+ path : ApiPath
300
+
301
+ def _score_name (self , path : ApiPath ) -> NameScore :
295
302
"""Return a tuple of scores indicating how to sort for the best name.
296
303
297
304
This function is meant to be used as the `key` to the `sorted` function.
@@ -307,18 +314,18 @@ def _score_name(self, name: str):
307
314
name: Fallback, sorts lexicographically on the full_name.
308
315
309
316
Args:
310
- name: the full name to score, for example `tf. estimator. Estimator`
317
+ path: APiPath to score, for example `('tf',' estimator',' Estimator') `
311
318
312
319
Returns:
313
320
A tuple of scores. When sorted the preferred name will have the lowest
314
321
value.
315
322
"""
316
- parts = name .split ('.' )
317
- short_name = parts [- 1 ]
318
- if len (parts ) == 1 :
319
- return (- 99 , - 99 , - 99 , - 99 , short_name )
323
+ py_object = self .path_tree [path ].py_object
324
+ if len (path ) == 1 :
325
+ return self .NameScore (- 99 , - 99 , - 99 , - 99 , path )
320
326
321
- container = self ._index .get ('.' .join (parts [:- 1 ]), name )
327
+ short_name = path [- 1 ]
328
+ container = self .path_tree [path [:- 1 ]].py_object
322
329
323
330
defining_class_score = 1
324
331
if inspect .isclass (container ):
@@ -327,30 +334,44 @@ def _score_name(self, name: str):
327
334
defining_class_score = - 1
328
335
329
336
experimental_score = - 1
330
- if 'contrib' in parts or any ('experimental' in part for part in parts ):
337
+ if 'contrib' in path or any ('experimental' in part for part in path ):
331
338
experimental_score = 1
332
339
333
340
keras_score = 1
334
- if 'keras' in parts :
341
+ if 'keras' in path :
335
342
keras_score = - 1
336
343
337
- while parts :
338
- container = self ._index ['.' .join (parts )]
344
+ if inspect .ismodule (py_object ):
345
+ # prefer short paths for modules
346
+ module_length_score = len (path )
347
+ else :
348
+ module_length_score = self ._get_module_length_score (path )
349
+
350
+ return self .NameScore (
351
+ defining_class_score = defining_class_score ,
352
+ experimental_score = experimental_score ,
353
+ keras_score = keras_score ,
354
+ module_length_score = module_length_score ,
355
+ path = path )
356
+
357
+ def _get_module_length_score (self , path ):
358
+ partial_path = list (path )
359
+ while partial_path :
360
+ container = self .path_tree [tuple (partial_path [:- 1 ])].py_object
361
+ partial_path .pop ()
339
362
if inspect .ismodule (container ):
340
363
break
341
- parts .pop ()
342
364
343
- module_length = len (parts )
365
+ module_length = len (partial_path )
344
366
345
- if len ( parts ) == 2 :
367
+ if module_length == 2 :
346
368
# `tf.submodule.thing` is better than `tf.thing`
347
369
module_length_score = - 1
348
370
else :
349
371
# shorter is better
350
372
module_length_score = module_length
351
373
352
- return (defining_class_score , experimental_score , keras_score ,
353
- module_length_score , name )
374
+ return module_length_score
354
375
355
376
def build (self ):
356
377
"""Compute data structures containing information about duplicates.
@@ -398,19 +419,20 @@ def build(self):
398
419
if not aliases :
399
420
aliases = [node ]
400
421
401
- names = [alias .full_name for alias in aliases ]
422
+ name_tuples = [alias .path for alias in aliases ]
402
423
403
- names = sorted (names )
404
424
# Choose the main name with a lexical sort on the tuples returned by
405
425
# by _score_name.
406
- main_name = min (names , key = self ._score_name )
426
+ main_name_tuple = min (name_tuples , key = self ._score_name )
427
+ main_name = '.' .join (main_name_tuple )
407
428
408
- if names :
409
- duplicates [main_name ] = list (names )
429
+ names = ['.' .join (name_tuple ) for name_tuple in name_tuples ]
430
+ if name_tuples :
431
+ duplicates [main_name ] = sorted (names )
410
432
411
- names .remove (main_name )
412
433
for name in names :
413
- duplicate_of [name ] = main_name
434
+ if name != main_name :
435
+ duplicate_of [name ] = main_name
414
436
415
437
# Set the reverse index to the canonical name.
416
438
if not maybe_singleton (py_object ):
@@ -552,8 +574,7 @@ def from_path_tree(cls, path_tree: PathTree, score_name_fn) -> 'ApiTree':
552
574
# been processed, so now we can choose its master name.
553
575
aliases = [node .path for node in duplicate_nodes ]
554
576
555
- master_path = min (['.' .join (a ) for a in aliases ], key = score_name_fn )
556
- master_path = tuple (master_path .split ('.' ))
577
+ master_path = min (aliases , key = score_name_fn )
557
578
558
579
self .insert (master_path , current_node .py_object , aliases )
559
580
0 commit comments