Skip to content

Commit

Permalink
fix: disambiguate all entry names to clarify duplicate names (#72)
Browse files Browse the repository at this point in the history
* feat: deduplicate all entry names in yaml_data

* test: update unittest for disambiguate_toc_name
  • Loading branch information
dandhlee committed Jul 21, 2021
1 parent bb432e7 commit b632eb7
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 32 deletions.
82 changes: 53 additions & 29 deletions docfx_yaml/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -813,8 +813,12 @@ def find_unique_name(package_name, entries):
return [package_name[-1]]

# Used to disambiguate names that have same entries.
# Returns a dictionary of names that are disambiguated in the form of:
# {uidname: disambiguated_name}
def disambiguate_toc_name(toc_yaml):
name_entries = {}
disambiguated_names = {}

for module in toc_yaml:
module_name = module['name']
if module_name not in name_entries:
Expand All @@ -833,13 +837,17 @@ def disambiguate_toc_name(toc_yaml):
name_entries[module_name][module_name] = 1

if 'items' in module:
disambiguate_toc_name(module['items'])
# Update the dictionary of dismabiguated names
disambiguated_names.update(disambiguate_toc_name(module['items']))

for module in toc_yaml:
module_name = module['name']
# Check if there are multiple entires of module['name'], disambiguate if needed.
if name_entries[module_name][module_name] > 1:
module['name'] = ".".join(find_unique_name(module['uidname'].split("."), name_entries[module_name]))
disambiguated_names[module['uidname']] = module['name']

return disambiguated_names

def build_finished(app, exception):
"""
Expand Down Expand Up @@ -891,6 +899,9 @@ def convert_module_to_package_if_needed(obj):
# caused by Windows case insensitive file system
file_name_set = set()

# Used to disambiguate entry names
yaml_map = {}

# Order matters here, we need modules before lower level classes,
# so that we can make sure to inject the TOC properly
for data_set in (app.env.docfx_yaml_modules,
Expand Down Expand Up @@ -1020,33 +1031,7 @@ def convert_module_to_package_if_needed(obj):
obj['source']['remote']['repo'] == 'https://apidrop.visualstudio.com/Content%20CI/_git/ReferenceAutomation'):
del(obj['source'])

# Output file
if uid.lower() in file_name_set:
filename = uid + "(%s)" % app.env.docfx_info_uid_types[uid]
else:
filename = uid

out_file = os.path.join(normalized_outdir, '%s.yml' % filename)
ensuredir(os.path.dirname(out_file))
if app.verbosity >= 1:
app.info(bold('[docfx_yaml] ') + darkgreen('Outputting %s' % filename))

with open(out_file, 'w') as out_file_obj:
out_file_obj.write('### YamlMime:UniversalReference\n')
try:
dump(
{
'items': yaml_data,
'references': references,
'api_name': [], # Hack around docfx YAML
},
out_file_obj,
default_flow_style=False
)
except Exception as e:
raise ValueError("Unable to dump object\n{0}".format(yaml_data)) from e

file_name_set.add(filename)
yaml_map[uid] = [yaml_data, references]

# Parse the name of the object.
# Some types will need additional parsing to de-duplicate their names and contain
Expand Down Expand Up @@ -1088,7 +1073,7 @@ def convert_module_to_package_if_needed(obj):
raise RuntimeError("No documentation for this module.")

# Perform additional disambiguation of the name
disambiguate_toc_name(toc_yaml)
disambiguated_names = disambiguate_toc_name(toc_yaml)

# Keeping uidname field carrys over onto the toc.yaml files, we need to
# be keep using them but don't need them in the actual file
Expand Down Expand Up @@ -1139,6 +1124,45 @@ def convert_module_to_package_if_needed(obj):
default_flow_style=False
)

# Output files
for uid, data in iter(yaml_map.items()):

for yaml_item in data:
for obj in yaml_item:
# If the entry was disambiguated, update here:
obj_full_name = obj['fullName']
if disambiguated_names.get(obj_full_name):
obj['name'] = disambiguated_names[obj_full_name]

# data is formatted as [yaml_data, references]
yaml_data, references = data

if uid.lower() in file_name_set:
filename = uid + "(%s)" % app.env.docfx_info_uid_types[uid]
else:
filename = uid

out_file = os.path.join(normalized_outdir, '%s.yml' % filename)
ensuredir(os.path.dirname(out_file))
if app.verbosity >= 1:
app.info(bold('[docfx_yaml] ') + darkgreen('Outputting %s' % filename))

with open(out_file, 'w') as out_file_obj:
out_file_obj.write('### YamlMime:UniversalReference\n')
try:
dump(
{
'items': yaml_data,
'references': references,
'api_name': [], # Hack around docfx YAML
},
out_file_obj,
default_flow_style=False
)
except Exception as e:
raise ValueError("Unable to dump object\n{0}".format(yaml_data)) from e

file_name_set.add(filename)

def missing_reference(app, env, node, contnode):
reftarget = ''
Expand Down
17 changes: 14 additions & 3 deletions tests/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,30 +38,41 @@ def test_disambiguate_toc_name(self):

want_file = open('tests/yaml_post.yaml', 'r')
yaml_want = load(want_file, Loader=Loader)
disambiguated_names_want = {
'google.cloud.spanner_admin_database_v1.types': 'spanner_admin_database_v1.types',
'google.cloud.spanner_admin_instance_v1.types': 'spanner_admin_instance_v1.types',
'google.cloud.spanner_v1.types': 'spanner_v1.types'
}

test_file = open('tests/yaml_pre.yaml', 'r')
yaml_got = load(test_file, Loader=Loader)
disambiguate_toc_name(yaml_got)
disambiguated_names_got = disambiguate_toc_name(yaml_got)

want_file.close()
test_file.close()

self.assertEqual(yaml_want, yaml_got)
self.assertEqual(disambiguated_names_want, disambiguated_names_got)


def test_disambiguate_toc_name_duplicate(self):

want_file = open('tests/yaml_post_duplicate.yaml', 'r')
yaml_want = load(want_file, Loader=Loader)

disambiguated_names_want = {
'google.api_core.client_info': 'client_info',
'google.api_core.gapic_v1.client_info': 'gapic_v1.client_info'
}

test_file = open('tests/yaml_pre_duplicate.yaml', 'r')
yaml_got = load(test_file, Loader=Loader)
disambiguate_toc_name(yaml_got)
disambiguated_names_got = disambiguate_toc_name(yaml_got)

want_file.close()
test_file.close()

self.assertEqual(yaml_want, yaml_got)
self.assertEqual(disambiguated_names_want, disambiguated_names_got)


def test_reference_in_summary(self):
Expand Down

0 comments on commit b632eb7

Please sign in to comment.