Check that an api dict is valid (does not use the same index twice) and removed `__unused_indices__` from it (which is important only here)
(d)
| 463 | return ret |
| 464 | |
| 465 | def check_api_dict(d): |
| 466 | """Check that an api dict is valid (does not use the same index twice) |
| 467 | and removed `__unused_indices__` from it (which is important only here) |
| 468 | """ |
| 469 | # Pop the `__unused_indices__` field: These are known holes: |
| 470 | removed = set(d.pop("__unused_indices__", [])) |
| 471 | # remove the extra value fields that aren't the index |
| 472 | index_d = {k: v[0] for k, v in d.items()} |
| 473 | |
| 474 | # We have if a same index is used twice: we 'revert' the dict so that index |
| 475 | # become keys. If the length is different, it means one index has been used |
| 476 | # at least twice |
| 477 | revert_dict = {v: k for k, v in index_d.items()} |
| 478 | if not len(revert_dict) == len(index_d): |
| 479 | # We compute a dict index -> list of associated items |
| 480 | doubled = {} |
| 481 | for name, index in index_d.items(): |
| 482 | try: |
| 483 | doubled[index].append(name) |
| 484 | except KeyError: |
| 485 | doubled[index] = [name] |
| 486 | fmt = "Same index has been used twice in api definition: {}" |
| 487 | val = ''.join( |
| 488 | f'\n\tindex {index} -> {names}' |
| 489 | for index, names in doubled.items() if len(names) != 1 |
| 490 | ) |
| 491 | raise ValueError(fmt.format(val)) |
| 492 | |
| 493 | # No 'hole' in the indexes may be allowed, and it must starts at 0 |
| 494 | indexes = set(index_d.values()) |
| 495 | expected = set(range(len(indexes) + len(removed))) |
| 496 | if not indexes.isdisjoint(removed): |
| 497 | raise ValueError("API index used but marked unused: " |
| 498 | f"{indexes.intersection(removed)}") |
| 499 | if indexes.union(removed) != expected: |
| 500 | diff = expected.symmetric_difference(indexes.union(removed)) |
| 501 | msg = f"There are some holes in the API indexing: (symmetric diff is {diff})" |
| 502 | raise ValueError(msg) |
| 503 | |
| 504 | def get_api_functions(tagname, api_dict): |
| 505 | """Parse source files to get functions tagged by the given tag.""" |