Recursively finds Python files and returns their content and AST. Args: path: File or directory to scan. enable_syntax_warnings: When True, SyntaxWarning is treated as an error and the offending file is excluded from results. _stats_meta: Optional dict t
(
path: Path,
enable_syntax_warnings: bool = False,
_stats_meta: Optional[Dict[str, int]] = None,
debug: bool = False,
exclude: Optional[List[str]] = None,
cache: Optional[IncrementalAstCache] = None,
)
| 179 | abs_str = str(file_path).replace("\\", "/") |
| 180 | parts = set(rel.parts) | set(file_path.parts) |
| 181 | for pat in patterns: |
| 182 | if fnmatch.fnmatch(rel_str, pat) or fnmatch.fnmatch(abs_str, pat): |
| 183 | return True |
| 184 | if pat in parts: |
| 185 | return True |
| 186 | return False |
| 187 | |
| 188 | |
| 189 | def get_python_file_asts( |
| 190 | path: Path, |
| 191 | enable_syntax_warnings: bool = False, |
| 192 | _stats_meta: Optional[Dict[str, int]] = None, |
| 193 | debug: bool = False, |
| 194 | exclude: Optional[List[str]] = None, |
| 195 | cache: Optional[IncrementalAstCache] = None, |
| 196 | ) -> List[Dict[str, Any]]: |
| 197 | """ |
| 198 | Recursively finds Python files and returns their content and AST. |
| 199 | |
| 200 | Args: |
| 201 | path: File or directory to scan. |
| 202 | enable_syntax_warnings: When True, SyntaxWarning is treated as an |
| 203 | error and the offending file is excluded from results. |
| 204 | _stats_meta: Optional dict that will be populated with |
| 205 | ``{'skipped': N, 'errors': N}`` for use by StatsCollector. |
| 206 | Defaults to None (no tracking). Backward-compatible: callers |
| 207 | that do not pass this argument are unaffected. |
| 208 | cache: Optional incremental AST cache. When supplied (and syntax |
| 209 | warnings are not being promoted to errors), the cached AST JSON |
| 210 | is reused instead of re-running ast.parse + json.dumps. The cache |
| 211 | suppresses SyntaxWarning internally, so it is bypassed whenever |
| 212 | ``enable_syntax_warnings`` is True to preserve that diagnostic. |
| 213 | """ |
| 214 | if _stats_meta is not None: |
| 215 | _stats_meta['skipped'] = 0 |
| 216 | _stats_meta['errors'] = 0 |
| 217 | |
| 218 | results = [] |
| 219 | exclude_patterns = list(exclude or []) |
| 220 | root = path if path.is_dir() else path.parent |
| 221 | if path.is_dir(): |
| 222 | files_to_scan = [ |
| 223 | p for p in path.glob("**/*.py") |
| 224 | if not _is_path_excluded(p, root, exclude_patterns) |
| 225 | ] |
| 226 | else: |
| 227 | files_to_scan = [path] |
| 228 | |
| 229 | with warnings.catch_warnings(): |
| 230 | if not enable_syntax_warnings: |
| 231 | warnings.filterwarnings('ignore', category=SyntaxWarning) |
| 232 | else: |
| 233 | warnings.filterwarnings('error', category=SyntaxWarning) |
| 234 | |
| 235 | for py_file in files_to_scan: |
| 236 | if py_file.is_file(): |
| 237 | display_path = ( |
| 238 | py_file.relative_to(path) if path.is_dir() else py_file.name |