Processor that can run multiple checkers on files. Caches file content across process_files_with_checkers() calls so that files read in one scope are not re-read when processed in another scope.
| 149 | |
| 150 | |
| 151 | class MultiCheckerFileProcessor: |
| 152 | """Processor that can run multiple checkers on files. |
| 153 | |
| 154 | Caches file content across process_files_with_checkers() calls so that |
| 155 | files read in one scope are not re-read when processed in another scope. |
| 156 | """ |
| 157 | |
| 158 | def __init__(self): |
| 159 | self._file_cache: dict[str, FileContent] = {} |
| 160 | |
| 161 | def _get_file_content(self, file_path: str) -> FileContent: |
| 162 | """Read file content, using cache to avoid redundant I/O. |
| 163 | |
| 164 | Args: |
| 165 | file_path: Path to the file to read |
| 166 | |
| 167 | Returns: |
| 168 | Cached or freshly-read FileContent object |
| 169 | |
| 170 | Raises: |
| 171 | OSError: If the file cannot be read |
| 172 | """ |
| 173 | if file_path not in self._file_cache: |
| 174 | with open(file_path, "r", encoding="utf-8") as f: |
| 175 | content = f.read() |
| 176 | self._file_cache[file_path] = FileContent( |
| 177 | path=file_path, content=content, lines=content.splitlines() |
| 178 | ) |
| 179 | return self._file_cache[file_path] |
| 180 | |
| 181 | def process_files_with_checkers( |
| 182 | self, file_paths: list[str], checkers: list[FileContentChecker] |
| 183 | ) -> dict[str, list[str]]: |
| 184 | """Process files with multiple checkers. |
| 185 | |
| 186 | Args: |
| 187 | file_paths: List of file paths to process |
| 188 | checkers: List of checker instances to run on the files |
| 189 | |
| 190 | Returns: |
| 191 | Dictionary mapping checker class name to list of issues found |
| 192 | """ |
| 193 | # Initialize results dictionary for each checker |
| 194 | results: dict[str, list[str]] = {} |
| 195 | for checker in checkers: |
| 196 | checker_name = checker.__class__.__name__ |
| 197 | results[checker_name] = [] |
| 198 | |
| 199 | # Process each file |
| 200 | for file_path in file_paths: |
| 201 | # Check if any checker wants to process this file |
| 202 | interested_checkers = [ |
| 203 | checker |
| 204 | for checker in checkers |
| 205 | if checker.should_process_file(file_path) |
| 206 | ] |
| 207 | |
| 208 | # If any checker is interested, read the file once (or use cache) |
no outgoing calls