Last active
September 2, 2022 14:02
-
-
Save conqp/6056221a20414b83f4af1d515595d104 to your computer and use it in GitHub Desktop.
Find for- and while-loops with else clauses
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
"""Find for- and while-loops with else clauses.""" | |
from ast import For, Module, While, parse, walk | |
from logging import getLogger | |
from pathlib import Path | |
from typing import Iterator | |
LOGGER = getLogger(__file__) | |
def iter_loops(module: Module) -> Iterator[For | While]: | |
"""Yield loop nodes of the given module.""" | |
for node in walk(module): | |
if isinstance(node, (For, While)): | |
yield node | |
def python_modules(root: Path) -> Iterator[tuple[Path, Module]]: | |
"""Recursively yield file names and Python modules | |
loaded from files within the given root directory. | |
""" | |
for filename in root.rglob('*.py'): | |
try: | |
module = parse(filename.read_text()) | |
except PermissionError: | |
LOGGER.error('Insufficient permissions to read: %s', filename) | |
except SyntaxError: | |
LOGGER.error('Invalid syntax in: %s', filename) | |
else: | |
yield filename, module | |
def main() -> None: | |
"""Run the program.""" | |
for filename, module in python_modules(Path.cwd()): | |
for loop in iter_loops(module): | |
if loop.orelse: | |
print( | |
f'{filename}: {loop.lineno}', | |
f'({type(loop).__name__.casefold()})' | |
) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment