Skip to content

Instantly share code, notes, and snippets.

@MaggieMoss
Last active August 27, 2020 16:24
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 MaggieMoss/815e010bde5f868511d0919e11dda79d to your computer and use it in GitHub Desktop.
Save MaggieMoss/815e010bde5f868511d0919e11dda79d to your computer and use it in GitHub Desktop.
from typing import List, Optional, Sequence
from pathlib import Path
import libcst as cst
from libcst import matchers as m
def _get_paths(target_directory: Path) -> List[Path]:
return [
path
for path in target_directory.glob("**/*.py")
if not path.name.startswith("__") and not path.name.startswith(".")
]
def _parse_paths(paths: List[Path]) -> List[Path]:
parsed_paths = []
for path in paths:
if path.is_dir():
parsed_directory_paths = _get_paths(path)
for path in parsed_directory_paths:
parsed_paths.append(path)
else:
parsed_paths.append(path)
return parsed_paths
def parse_path_to_module(path: Path) -> Optional[cst.Module]:
try:
return cst.parse_module(path.read_text())
except (ParserSyntaxError, FileNotFoundError):
return None
def is_optional(node) -> bool:
return m.matches(node, m.Name(value="Optional"))
class AnnotationsCollector(cst.CSTVisitor):
def __init__(self) -> None:
self.optional_count = 0
self.annotation_count = 0
def visit_Annotation(self, node: cst.Annotation) -> None:
self.annotation_count += 1
# iter through to find optional counts
def subscript_iter(node):
try:
if m.matches(node, m.Subscript()):
if is_optional(node.value):
self.optional_count += 1
else:
for a in node.slice:
value = a.slice.value
if is_optional(value):
self.optional_count += 1
if m.matches(value, m.Subscript()):
subscript_iter(value)
except Exception:
pass
annotation_node = node.annotation
subscript_iter(annotation_node)
if __name__ == "__main__":
paths = _parse_paths([Path("/path/to/project/root")])
collector = AnnotationsCollector()
for path in paths:
module = parse_path_to_module(path)
module.visit(collector)
print(collector.annotation_count)
print(collector.optional_count)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment