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

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

2 

3from abc import ABCMeta, abstractmethod 

4from pathlib import Path 

5 

6from sel_tools.utils.config import ( 

7 CMAKE_FILE_ENDING, 

8 CMAKELISTS_FILE_NAME, 

9 CPP_FILE_ENDINGS, 

10) 

11 

12 

13class FileVisitor: 

14 """Interface for file visitor. 

15 

16 Children implement visit_file 

17 """ 

18 

19 __metaclass__ = ABCMeta 

20 

21 @abstractmethod 

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

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

24 raise NotImplementedError(msg) 

25 

26 

27class FileTree: 

28 """Caller of the visitor pattern. 

29 

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

31 file in item 

32 """ 

33 

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

35 self._item = item 

36 

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) 

47 

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 ) 

54 

55 

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) 

59 

60 

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