Coverage for src/mkdocstrings_handlers/python/rendering.py: 100.00%

24 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-03-09 18:38 +0100

1"""This module implements rendering utilities.""" 

2 

3import sys 

4from typing import Any, Callable 

5 

6from markupsafe import Markup 

7from mkdocstrings import CollectorItem, get_logger 

8 

9log = get_logger(__name__) 

10 

11 

12def do_brief_xref(path: str) -> Markup: 

13 """Filter to create cross-reference with brief text and full identifier as hover text. 

14 

15 Arguments: 

16 path: The path to shorten and render. 

17 

18 Returns: 

19 A span containing the brief cross-reference and the full one on hover. 

20 """ 

21 brief = path.split(".")[-1] 

22 return Markup("<autoref identifier={path} optional hover>{brief}</autoref>").format(path=path, brief=brief) 

23 

24 

25def sort_object(obj: CollectorItem, sort_function: Callable[[CollectorItem], Any]) -> None: 

26 """Sort the collected object's children. 

27 

28 Sorts the object's children list, then each category separately, and then recurses into each. 

29 

30 Arguments: 

31 obj: The collected object, as a dict. Note that this argument is mutated. 

32 sort_function: The sort key function used to determine the order of elements. 

33 """ 

34 obj["children"].sort(key=sort_function) 

35 

36 for category in ("attributes", "classes", "functions", "methods", "modules"): 

37 obj[category].sort(key=sort_function) 

38 

39 for child in obj["children"]: 

40 sort_object(child, sort_function=sort_function) 

41 

42 

43def sort_key_alphabetical(item: CollectorItem) -> Any: 

44 """Return an item's name or the final unicode character. 

45 

46 Arguments: 

47 item: A collected item. 

48 

49 Returns: 

50 Name or final unicode character. 

51 """ 

52 # chr(sys.maxunicode) is a string that contains the final unicode 

53 # character, so if 'name' isn't found on the object, the item will go to 

54 # the end of the list. 

55 return item.get("name", chr(sys.maxunicode)) 

56 

57 

58def sort_key_source(item: CollectorItem) -> Any: 

59 """Return an item's starting line number or -1. 

60 

61 Arguments: 

62 item: A collected item. 

63 

64 Returns: 

65 Starting line number or -1. 

66 """ 

67 # if 'line_start' isn't found on the object, the item will go to 

68 # the start of the list. 

69 return item.get("source", {}).get("line_start", -1) 

70 

71 

72def rebuild_category_lists(obj: dict) -> None: 

73 """Recursively rebuild the category lists of a collected object. 

74 

75 Since `pytkdocs` dumps JSON on standard output, it must serialize the object-tree and flatten it to reduce data 

76 duplication and avoid cycle-references. Indeed, each node of the object-tree has a `children` list, containing 

77 all children, and another list for each category of children: `attributes`, `classes`, `functions`, `methods` 

78 and `modules`. It replaces the values in category lists with only the paths of the objects. 

79 

80 Here, we reconstruct these category lists by picking objects in the `children` list using their path. 

81 

82 For each object, we recurse on every one of its children. 

83 

84 Arguments: 

85 obj: The collected object, loaded back from JSON into a Python dictionary. 

86 """ 

87 for category in ("attributes", "classes", "functions", "methods", "modules"): 

88 obj[category] = [obj["children"][path] for path in obj[category]] 

89 obj["children"] = [child for _, child in obj["children"].items()] 

90 for child in obj["children"]: 

91 rebuild_category_lists(child)