Coverage for jutil/files.py: 86%

47 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-10-07 16:40 -0500

1import os 

2from typing import List 

3from django.utils.translation import gettext as _ 

4from jutil.format import is_media_full_path, strip_media_root 

5 

6 

7def list_files(dir_name: str, suffix: str = "", ignore_case: bool = True, use_media_root: bool = False, recurse: bool = False) -> List[str]: 

8 """ 

9 Lists all files under specified directory. 

10 Optionally filter files by suffix and recurse to subdirectories. 

11 :param dir_name: Directory path 

12 :param suffix: Case-sensitive suffix (optional) 

13 :param ignore_case: Case-insensitive suffix. Default is True. 

14 :param use_media_root: Instead of full path return files relative to media root. 

15 :param recurse: Recurse subdirectories (optional) 

16 :return: List of file names found 

17 """ 

18 if not os.path.isdir(dir_name): 18 ↛ 19line 18 didn't jump to line 19, because the condition on line 18 was never true

19 raise ValueError(_("{} is not a directory").format(dir_name)) 

20 dir_full_path = os.path.abspath(dir_name) 

21 if use_media_root and not is_media_full_path(dir_full_path): 21 ↛ 22line 21 didn't jump to line 22, because the condition on line 21 was never true

22 raise ValueError(_("{} is not under MEDIA_ROOT")) 

23 

24 if suffix: 24 ↛ 30line 24 didn't jump to line 30, because the condition on line 24 was never false

25 if not suffix.startswith("."): 25 ↛ 26line 25 didn't jump to line 26, because the condition on line 25 was never true

26 suffix = "." + suffix 

27 if ignore_case: 

28 suffix = suffix.lower() 

29 

30 out: List[str] = [] 

31 for ent in os.scandir(dir_full_path): 

32 assert isinstance(ent, os.DirEntry) 

33 if ent.is_file(): 

34 name = ent.name 

35 if suffix and ignore_case: 

36 name = name.lower() 

37 if not suffix or name.endswith(suffix): 

38 file_path = strip_media_root(ent.path) if use_media_root else os.path.abspath(ent.path) 

39 out.append(file_path) 

40 elif recurse and ent.is_dir() and ent.name != "." and ent.name != "..": 

41 out.extend(list_files(ent.path, suffix=suffix, ignore_case=ignore_case, use_media_root=use_media_root, recurse=recurse)) 

42 return out 

43 

44 

45def find_file(filename: str, dir_name: str = ".", use_media_root: bool = False, recurse: bool = False) -> List[str]: 

46 """ 

47 Finds file under specified directory. 

48 Optionally filter files by suffix and recurse to subdirectories. 

49 :param filename: File name to find. You can also specify relative paths e.g. "en/LC_MESSAGES/django.po" 

50 :param dir_name: Directory path. Default '.' 

51 :param use_media_root: Instead of full path return files relative to media root. 

52 :return: List of file names found 

53 :param recurse: Recurse subdirectories (optional) 

54 """ 

55 if not os.path.isdir(dir_name): 55 ↛ 56line 55 didn't jump to line 56, because the condition on line 55 was never true

56 raise ValueError(_("{} is not a directory").format(dir_name)) 

57 dir_full_path = os.path.abspath(dir_name) 

58 if use_media_root and not is_media_full_path(dir_full_path): 58 ↛ 59line 58 didn't jump to line 59, because the condition on line 58 was never true

59 raise ValueError(_("{} is not under MEDIA_ROOT")) 

60 out: List[str] = [] 

61 if "/" not in filename: 

62 filename = "/" + filename 

63 for ent in os.scandir(dir_full_path): 

64 assert isinstance(ent, os.DirEntry) 

65 if ent.is_file(): 

66 full_path = str(os.path.abspath(ent.path)) 

67 if full_path.endswith(filename): 

68 file_path = strip_media_root(full_path) if use_media_root else full_path 

69 out.append(file_path) 

70 elif recurse and ent.is_dir() and ent.name != "." and ent.name != "..": 

71 out.extend(find_file(filename, dir_name=ent.path, use_media_root=use_media_root, recurse=recurse)) 

72 return out