Skip to content

Instantly share code, notes, and snippets.

@conqp
Last active September 2, 2022 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save conqp/6056221a20414b83f4af1d515595d104 to your computer and use it in GitHub Desktop.
Save conqp/6056221a20414b83f4af1d515595d104 to your computer and use it in GitHub Desktop.
Find for- and while-loops with else clauses
#!/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