Coverage for src/jsoncrack_for_sphinx/core/autodoc.py: 80%

80 statements  

« prev     ^ index     » next       coverage.py v7.10.0, created at 2025-07-24 22:26 +0000

1""" 

2Autodoc integration for automatic schema inclusion. 

3""" 

4 

5from pathlib import Path 

6from typing import Any, Dict, List, Optional, Tuple 

7 

8from sphinx.application import Sphinx 

9from sphinx.util import logging 

10 

11from ..config.config_utils import get_jsoncrack_config 

12from ..generators.html_generator import generate_schema_html 

13from ..schema.schema_finder import find_schema_for_object 

14 

15logger = logging.getLogger(__name__) 

16 

17 

18def autodoc_process_signature( 

19 app: Sphinx, 

20 what: str, 

21 name: str, 

22 obj: Any, 

23 options: Dict[str, Any], 

24 signature: str, 

25 return_annotation: str, 

26) -> Optional[Tuple[str, str]]: 

27 """Process autodoc signatures and add schema information.""" 

28 logger.debug(f"Processing signature for {what}: {name}") 

29 

30 # Get configuration 

31 jsoncrack_config = get_jsoncrack_config(app.config) 

32 

33 # Check if autodoc is disabled 

34 if jsoncrack_config.disable_autodoc: 

35 logger.debug("Autodoc is disabled in configuration") 

36 return None 

37 

38 # Check if this object should be ignored 

39 for ignore_pattern in jsoncrack_config.autodoc_ignore: 

40 if name.startswith(ignore_pattern): 

41 logger.debug(f"Ignoring {name} due to pattern: {ignore_pattern}") 

42 return None 

43 

44 if what not in ("function", "method", "class"): 

45 logger.debug(f"Skipping {what} (not function/method/class)") 

46 return None 

47 

48 config = app.config 

49 schema_dir = getattr(config, "json_schema_dir", None) 

50 

51 if not schema_dir: 

52 logger.debug("No json_schema_dir configured, skipping schema search") 

53 return None 

54 

55 logger.debug(f"Searching for schema for {name} in {schema_dir}") 

56 

57 # Get search policy from configuration 

58 search_policy = jsoncrack_config.search_policy 

59 logger.debug(f"Using search policy from config: {search_policy}") 

60 

61 # Find schema file 

62 schema_result = find_schema_for_object(name, schema_dir, search_policy) 

63 if not schema_result: 

64 logger.debug(f"No schema found for {name}") 

65 return None 

66 

67 schema_path, file_type = schema_result 

68 logger.info(f"Found schema for {name}: {schema_path} (type: {file_type})") 

69 

70 # Store schema path and type to be used later 

71 if not hasattr(app.env, "_jsoncrack_schema_paths"): 

72 setattr(app.env, "_jsoncrack_schema_paths", {}) 

73 

74 schema_paths = getattr(app.env, "_jsoncrack_schema_paths") 

75 schema_paths[name] = (str(schema_path), file_type) 

76 logger.debug(f"Stored schema path for {name}") 

77 

78 return None 

79 

80 

81def autodoc_process_docstring( 

82 app: Sphinx, 

83 what: str, 

84 name: str, 

85 obj: Any, 

86 options: Dict[str, Any], 

87 lines: List[str], 

88) -> None: 

89 """Process docstrings and add schema HTML.""" 

90 logger.debug(f"Processing docstring for {what}: {name}") 

91 

92 # Get configuration 

93 jsoncrack_config = get_jsoncrack_config(app.config) 

94 

95 # Check if autodoc is disabled 

96 if jsoncrack_config.disable_autodoc: 

97 logger.debug("Autodoc is disabled in configuration") 

98 return 

99 

100 # Check if this object should be ignored 

101 for ignore_pattern in jsoncrack_config.autodoc_ignore: 

102 if name.startswith(ignore_pattern): 

103 logger.debug(f"Ignoring {name} due to pattern: {ignore_pattern}") 

104 return 

105 

106 if what not in ("function", "method", "class"): 

107 logger.debug(f"Skipping {what} (not function/method/class)") 

108 return 

109 

110 if not hasattr(app.env, "_jsoncrack_schema_paths"): 

111 logger.debug("No schema paths stored, skipping") 

112 return 

113 

114 schema_paths = getattr(app.env, "_jsoncrack_schema_paths") 

115 schema_data = schema_paths.get(name) 

116 if not schema_data: 

117 logger.debug(f"No schema data found for {name}") 

118 return 

119 

120 logger.debug(f"Processing schema for {name}: {schema_data}") 

121 

122 if isinstance(schema_data, str): 

123 # Backward compatibility: if it's just a string, assume it's a schema file 

124 schema_path_str = schema_data 

125 file_type = "schema" 

126 else: 

127 schema_path_str, file_type = schema_data 

128 

129 schema_path = Path(schema_path_str) 

130 

131 if not schema_path.exists(): 

132 logger.error(f"Schema file does not exist: {schema_path}") 

133 return 

134 

135 logger.info(f"Adding schema to docstring for {name}: {schema_path}") 

136 

137 # Generate schema HTML 

138 try: 

139 html_content = generate_schema_html(schema_path, file_type, app.config) 

140 logger.debug(f"Generated HTML content for {name} (length: {len(html_content)})") 

141 except Exception as e: 

142 logger.error(f"Error generating schema HTML for {name}: {e}") 

143 return 

144 

145 # Add schema HTML to docstring 

146 lines.extend( 

147 [ 

148 "", 

149 ".. raw:: html", 

150 "", 

151 f" {html_content}", 

152 "", 

153 ] 

154 ) 

155 logger.debug(f"Added schema HTML to docstring for {name}")