Build hierarchical tree grouped by module type, then by module structure. Args: file_stats: List of FileStats objects Returns: Dictionary mapping module types to their tree roots
(file_stats: List[FileStats])
| 229 | |
| 230 | @staticmethod |
| 231 | def build_file_tree(file_stats: List[FileStats]) -> Dict[str, TreeNode]: |
| 232 | """Build hierarchical tree grouped by module type, then by module structure. |
| 233 | |
| 234 | Args: |
| 235 | file_stats: List of FileStats objects |
| 236 | |
| 237 | Returns: |
| 238 | Dictionary mapping module types to their tree roots |
| 239 | """ |
| 240 | # Group by module type first |
| 241 | type_groups = {'stdlib': [], 'site-packages': [], 'project': [], 'other': []} |
| 242 | for stat in file_stats: |
| 243 | type_groups[stat.module_type].append(stat) |
| 244 | |
| 245 | # Build tree for each type |
| 246 | trees = {} |
| 247 | for module_type, stats in type_groups.items(): |
| 248 | if not stats: |
| 249 | continue |
| 250 | |
| 251 | root_node = TreeNode() |
| 252 | |
| 253 | for stat in stats: |
| 254 | module_name = stat.module_name |
| 255 | parts = module_name.split('.') |
| 256 | |
| 257 | # Navigate/create tree structure |
| 258 | current_node = root_node |
| 259 | for i, part in enumerate(parts): |
| 260 | if i == len(parts) - 1: |
| 261 | # Last part - store the file |
| 262 | current_node.files.append(stat) |
| 263 | else: |
| 264 | # Intermediate part - create or navigate |
| 265 | if part not in current_node.children: |
| 266 | current_node.children[part] = TreeNode() |
| 267 | current_node = current_node.children[part] |
| 268 | |
| 269 | # Calculate aggregate stats for this type's tree |
| 270 | _TreeBuilder._calculate_node_stats(root_node) |
| 271 | trees[module_type] = root_node |
| 272 | |
| 273 | return trees |
| 274 | |
| 275 | @staticmethod |
| 276 | def _calculate_node_stats(node: TreeNode) -> Tuple[int, int]: |
no test coverage detected