Coverage for src/extratools_core/path.py: 0%

54 statements  

« prev     ^ index     » next       coverage.py v7.8.1, created at 2025-06-26 03:51 -0700

1from collections.abc import Iterable 

2from datetime import UTC, datetime, timedelta 

3from io import StringIO 

4from pathlib import Path 

5 

6from .typing import PathLike 

7 

8 

9def clear_dir(curr_dir: PathLike) -> None: 

10 """ 

11 Based on example in https://docs.python.org/3/library/pathlib.html#pathlib.Path.walk 

12 """ 

13 

14 if not curr_dir.is_dir(): 

15 raise ValueError 

16 

17 for parent, dirs, files in curr_dir.walk(top_down=False): 

18 for filename in files: 

19 (parent / filename).unlink() 

20 for dirname in dirs: 

21 (parent / dirname).rmdir() 

22 

23 

24def rm_with_empty_parents( 

25 curr: PathLike, 

26 *, 

27 stop: PathLike | None = None, 

28) -> None: 

29 curr.unlink() 

30 

31 for parent in curr.parents: 

32 if parent == stop: 

33 return 

34 

35 if parent.is_dir() and next(iter(parent.iterdir()), None) is None: 

36 parent.rmdir() 

37 

38 

39def cleanup_dir_by_ttl( 

40 curr_dir: PathLike, 

41 ttl: timedelta | datetime, 

42 *, 

43 include_empty_parents: bool = True, 

44 return_before_delete: bool = False, 

45) -> Iterable[tuple[PathLike, datetime]]: 

46 if not curr_dir.is_dir(): 

47 raise ValueError 

48 

49 now: datetime = datetime.now(UTC) 

50 

51 for parent, _, files in curr_dir.walk(top_down=False): 

52 for filename in files: 

53 f: PathLike = (parent / filename) 

54 

55 last_modified_time: datetime = datetime.fromtimestamp(f.stat().st_mtime, UTC) 

56 if isinstance(ttl, timedelta): 

57 ttl = now - ttl 

58 

59 if last_modified_time < ttl: 

60 if return_before_delete: 

61 yield (f, last_modified_time) 

62 

63 if include_empty_parents: 

64 rm_with_empty_parents(f, stop=curr_dir) 

65 else: 

66 f.unlink() 

67 

68 if not return_before_delete: 

69 yield (f, last_modified_time) 

70 

71 

72def read_text_by_pattern( 

73 *patterns: str, 

74 pwd: Path | str | None = None, 

75 seperator: str | None = None, 

76 add_newline: bool = True, 

77) -> str: 

78 sio = StringIO() 

79 

80 pwd = Path() if not pwd else Path(pwd).expanduser() 

81 for pattern in patterns: 

82 for path in pwd.glob(pattern): 

83 if not path.is_file(): 

84 continue 

85 

86 file_content = path.read_text() 

87 sio.write(file_content) 

88 

89 if add_newline and file_content[-1] != "\n": 

90 sio.write("\n") 

91 

92 if seperator: 

93 sio.write(seperator) 

94 

95 content: str = sio.getvalue() 

96 sio.close() 

97 return content