Coverage for tools / sel_tools / utils / files.py: 100%

27 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-02 18:55 +0000

1"""File utils for software engineering tools.""" 

2 

3from abc import ABCMeta, abstractmethod 

4from pathlib import Path 

5 

6CMAKELISTS_FILE_NAME = "CMakeLists.txt" 

7 

8 

9class FileVisitor: 

10 """Interface for file visitor. 

11 

12 Children implement visit_file 

13 """ 

14 

15 __metaclass__ = ABCMeta 

16 

17 @abstractmethod 

18 def visit_file(self, file: Path) -> None: 

19 msg = "Don't call me, I'm abstract." 

20 raise NotImplementedError(msg) 

21 

22 

23class FileTree: 

24 """Caller of the visitor pattern. 

25 

26 Accepts visitors on it is file tree, applies FileVisitor.visit_file() to each 

27 file in item 

28 """ 

29 

30 def __init__(self, item: Path) -> None: 

31 self._item = item 

32 

33 def accept(self, visitor: FileVisitor) -> None: 

34 if self._item.is_file(): 

35 visitor.visit_file(self._item) 

36 elif self._item.is_dir(): 

37 for sub_item in self.rglob_but(".git"): 

38 if sub_item.is_file(): 

39 visitor.visit_file(sub_item) 

40 else: 

41 msg = f"Path {self._item} does not exist" 

42 raise FileNotFoundError(msg) 

43 

44 def rglob_but(self, ignore_folder: str) -> list[Path]: 

45 return sorted( 

46 set(self._item.rglob("*")) 

47 - set(self._item.rglob(ignore_folder)) 

48 - set((self._item / ignore_folder).rglob("*")) 

49 ) 

50 

51 

52def is_cmake(file: Path) -> bool: 

53 """Return true if the file is a cmake file, otherwise false.""" 

54 return (file.name == CMAKELISTS_FILE_NAME) or (file.suffix == ".cmake") 

55 

56 

57def is_cpp(file: Path) -> bool: 

58 """Return true if the file is a cpp file, otherwise false.""" 

59 return file.suffix in [".cpp", ".h", ".hpp"]