Coverage for jutil/files.py: 86%
47 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-07 16:40 -0500
« 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
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"))
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()
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
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