|
12 | 12 | from collections.abc import Callable
|
13 | 13 |
|
14 | 14 |
|
15 |
| -def with_prefix(prefix: str, *, mode: int = os.F_OK | os.X_OK, path: str | None = None) -> list[str]: |
| 15 | +def with_prefix( |
| 16 | + prefix: str, |
| 17 | + *, |
| 18 | + paths: list[str] | None = None, |
| 19 | + path: str | None = None, |
| 20 | + mode: int = os.F_OK | os.X_OK, |
| 21 | +) -> list[str]: |
16 | 22 | """
|
17 | 23 | Parameters:
|
18 | 24 | prefix: The prefix used for searching.
|
| 25 | + paths: The list of paths to check. If `None`, the mutually exclusive `path` parameter is used. |
| 26 | + path: The PATH to check, with each path separated by [`os.pathsep`][]. If `None`, the PATH environment |
| 27 | + variable is used. Mutually exclusive with `paths`. |
19 | 28 | mode: The file mode used for checking access.
|
20 |
| - path: The PATH to check. If `None`, the PATH environment variable is used. |
21 | 29 |
|
22 | 30 | Returns:
|
23 |
| - A list of absolute paths to executables that match the given prefix. |
| 31 | + A list of absolute paths to executables that start with the given prefix. |
24 | 32 | """
|
25 |
| - return with_condition(lambda entry: entry.name.startswith(prefix), mode=mode, path=path) |
| 33 | + return with_condition(lambda entry: entry.name.startswith(prefix), paths=paths, path=path, mode=mode) |
26 | 34 |
|
27 | 35 |
|
28 | 36 | def with_pattern(
|
29 |
| - pattern: str | re.Pattern[str], *, mode: int = os.F_OK | os.X_OK, path: str | None = None |
| 37 | + pattern: str | re.Pattern[str], |
| 38 | + *, |
| 39 | + paths: list[str] | None = None, |
| 40 | + path: str | None = None, |
| 41 | + mode: int = os.F_OK | os.X_OK, |
30 | 42 | ) -> list[str]:
|
31 | 43 | """
|
32 | 44 | Parameters:
|
33 | 45 | pattern: The pattern used for searching.
|
| 46 | + paths: The list of paths to check. If `None`, the mutually exclusive `path` parameter is used. |
| 47 | + path: The PATH to check, with each path separated by [`os.pathsep`][]. If `None`, the PATH environment |
| 48 | + variable is used. Mutually exclusive with `paths`. |
34 | 49 | mode: The file mode used for checking access.
|
35 |
| - path: The PATH to check. If `None`, the PATH environment variable is used. |
36 | 50 |
|
37 | 51 | Returns:
|
38 | 52 | A list of absolute paths to executables that match the given pattern.
|
39 | 53 | """
|
40 |
| - return with_condition(lambda entry: re.search(pattern, entry.name) is not None, mode=mode, path=path) |
| 54 | + return with_condition(lambda entry: re.search(pattern, entry.name) is not None, paths=paths, path=path, mode=mode) |
41 | 55 |
|
42 | 56 |
|
43 | 57 | def with_condition(
|
44 |
| - condition: Callable[[os.DirEntry], bool], *, mode: int = os.F_OK | os.X_OK, path: str | None = None |
| 58 | + condition: Callable[[os.DirEntry], bool], |
| 59 | + *, |
| 60 | + paths: list[str] | None = None, |
| 61 | + path: str | None = None, |
| 62 | + mode: int = os.F_OK | os.X_OK, |
45 | 63 | ) -> list[str]:
|
46 | 64 | """
|
47 | 65 | Parameters:
|
48 | 66 | condition: The condition used for searching.
|
| 67 | + paths: The list of paths to check. If `None`, the mutually exclusive `path` parameter is used. |
| 68 | + path: The PATH to check, with each path separated by [`os.pathsep`][]. If `None`, the PATH environment |
| 69 | + variable is used. Mutually exclusive with `paths`. |
49 | 70 | mode: The file mode used for checking access.
|
50 |
| - path: The PATH to check. If `None`, the PATH environment variable is used. |
51 | 71 |
|
52 | 72 | Returns:
|
53 |
| - A list of absolute paths to executables that match the given pattern. |
| 73 | + A list of absolute paths to executables that satisfy the given condition. |
54 | 74 | """
|
55 |
| - if path is None: |
| 75 | + |
| 76 | + search_paths: list[str] = [] |
| 77 | + if paths is not None: |
| 78 | + if path is not None: |
| 79 | + message = 'the `paths` and `path` parameters are mutually exclusive' |
| 80 | + raise ValueError(message) |
| 81 | + |
| 82 | + search_paths[:] = paths |
| 83 | + elif path is not None: |
| 84 | + search_paths[:] = path.split(os.pathsep) |
| 85 | + else: |
56 | 86 | path = os.environ.get('PATH', None)
|
57 | 87 | if path is None:
|
58 | 88 | path = path_fallback()
|
59 | 89 |
|
60 |
| - executables: list[str] = [] |
61 |
| - if not path: |
62 |
| - return executables |
| 90 | + search_paths[:] = path.split(os.pathsep) |
63 | 91 |
|
64 |
| - search_paths = path.split(os.pathsep) |
| 92 | + executables: list[str] = [] |
65 | 93 | seen = set()
|
66 | 94 | for search_path in search_paths:
|
67 |
| - if not os.path.isdir(search_path): |
| 95 | + if not (search_path and os.path.isdir(search_path)): |
68 | 96 | continue
|
69 | 97 |
|
70 | 98 | norm_path = os.path.normcase(search_path)
|
|
0 commit comments