Coverage for sel_tools/utils/files.py: 100%
27 statements
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-04 21:22 +0000
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-04 21:22 +0000
1"""File utils for software engineering tools."""
3from abc import ABCMeta, abstractmethod
4from pathlib import Path
6from sel_tools.utils.config import (
7 CMAKE_FILE_ENDING,
8 CMAKELISTS_FILE_NAME,
9 CPP_FILE_ENDINGS,
10)
13class FileVisitor:
14 """Interface for file visitor.
16 Children implement visit_file
17 """
19 __metaclass__ = ABCMeta
21 @abstractmethod
22 def visit_file(self, file: Path) -> None:
23 msg = "Don't call me, I'm abstract."
24 raise NotImplementedError(msg)
27class FileTree:
28 """Caller of the visitor pattern.
30 Accepts visitors on it is file tree, applies FileVisitor.visit_file() to each
31 file in item
32 """
34 def __init__(self, item: Path) -> None:
35 self._item = item
37 def accept(self, visitor: FileVisitor) -> None:
38 if self._item.is_file():
39 visitor.visit_file(self._item)
40 elif self._item.is_dir():
41 for sub_item in self.rglob_but(".git"):
42 if sub_item.is_file():
43 visitor.visit_file(sub_item)
44 else:
45 msg = f"Path {self._item} does not exist"
46 raise FileNotFoundError(msg)
48 def rglob_but(self, ignore_folder: str) -> list[Path]:
49 return sorted(
50 set(self._item.rglob("*"))
51 - set(self._item.rglob(ignore_folder))
52 - set((self._item / ignore_folder).rglob("*"))
53 )
56def is_cmake(file: Path) -> bool:
57 """Return true if the file is a cmake file, otherwise false."""
58 return (file.name == CMAKELISTS_FILE_NAME) or (file.suffix == CMAKE_FILE_ENDING)
61def is_cpp(file: Path) -> bool:
62 """Return true if the file is a cpp file, otherwise false."""
63 return file.suffix in CPP_FILE_ENDINGS