Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pathspec/pathspec.py: 36%
66 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:15 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:15 +0000
1"""
2This module provides an object oriented interface for pattern matching
3of files.
4"""
6import sys
7from collections.abc import (
8 Collection as CollectionType)
9from itertools import (
10 zip_longest)
11from os import (
12 PathLike)
13from typing import (
14 AnyStr,
15 Callable,
16 Collection,
17 Iterable,
18 Iterator,
19 Optional,
20 Type,
21 TypeVar,
22 Union)
24from . import util
25from .pattern import (
26 Pattern)
27from .util import (
28 StrPath,
29 TreeEntry,
30 _filter_patterns,
31 _is_iterable,
32 match_file,
33 normalize_file)
35Self = TypeVar("Self", bound="PathSpec")
36"""
37:class:`PathSpec` self type hint to support Python v<3.11 using PEP 673
38recommendation.
39"""
42class PathSpec(object):
43 """
44 The :class:`PathSpec` class is a wrapper around a list of compiled
45 :class:`.Pattern` instances.
46 """
48 def __init__(self, patterns: Iterable[Pattern]) -> None:
49 """
50 Initializes the :class:`PathSpec` instance.
52 *patterns* (:class:`~collections.abc.Collection` or :class:`~collections.abc.Iterable`)
53 yields each compiled pattern (:class:`.Pattern`).
54 """
56 self.patterns = patterns if isinstance(patterns, CollectionType) else list(patterns)
57 """
58 *patterns* (:class:`~collections.abc.Collection` of :class:`.Pattern`)
59 contains the compiled patterns.
60 """
62 def __eq__(self, other: object) -> bool:
63 """
64 Tests the equality of this path-spec with *other* (:class:`PathSpec`)
65 by comparing their :attr:`~PathSpec.patterns` attributes.
66 """
67 if isinstance(other, PathSpec):
68 paired_patterns = zip_longest(self.patterns, other.patterns)
69 return all(a == b for a, b in paired_patterns)
70 else:
71 return NotImplemented
73 def __len__(self) -> int:
74 """
75 Returns the number of compiled patterns this path-spec contains
76 (:class:`int`).
77 """
78 return len(self.patterns)
80 def __add__(self: Self, other: "PathSpec") -> Self:
81 """
82 Combines the :attr:`Pathspec.patterns` patterns from two
83 :class:`PathSpec` instances.
84 """
85 if isinstance(other, PathSpec):
86 return self.__class__(self.patterns + other.patterns)
87 else:
88 return NotImplemented
90 def __iadd__(self: Self, other: "PathSpec") -> Self:
91 """
92 Adds the :attr:`Pathspec.patterns` patterns from one :class:`PathSpec`
93 instance to this instance.
94 """
95 if isinstance(other, PathSpec):
96 self.patterns += other.patterns
97 return self
98 else:
99 return NotImplemented
101 @classmethod
102 def from_lines(
103 cls: Type[Self],
104 pattern_factory: Union[str, Callable[[AnyStr], Pattern]],
105 lines: Iterable[AnyStr],
106 ) -> Self:
107 """
108 Compiles the pattern lines.
110 *pattern_factory* can be either the name of a registered pattern
111 factory (:class:`str`), or a :class:`~collections.abc.Callable` used
112 to compile patterns. It must accept an uncompiled pattern (:class:`str`)
113 and return the compiled pattern (:class:`.Pattern`).
115 *lines* (:class:`~collections.abc.Iterable`) yields each uncompiled
116 pattern (:class:`str`). This simply has to yield each line so it can
117 be a :class:`io.TextIOBase` (e.g., from :func:`open` or
118 :class:`io.StringIO`) or the result from :meth:`str.splitlines`.
120 Returns the :class:`PathSpec` instance.
121 """
122 if isinstance(pattern_factory, str):
123 pattern_factory = util.lookup_pattern(pattern_factory)
125 if not callable(pattern_factory):
126 raise TypeError(f"pattern_factory:{pattern_factory!r} is not callable.")
128 if not _is_iterable(lines):
129 raise TypeError(f"lines:{lines!r} is not an iterable.")
131 patterns = [pattern_factory(line) for line in lines if line]
132 return cls(patterns)
134 def match_entries(
135 self,
136 entries: Iterable[TreeEntry],
137 separators: Optional[Collection[str]] = None,
138 ) -> Iterator[TreeEntry]:
139 """
140 Matches the entries to this path-spec.
142 *entries* (:class:`~collections.abc.Iterable` of :class:`~util.TreeEntry`)
143 contains the entries to be matched against :attr:`self.patterns <PathSpec.patterns>`.
145 *separators* (:class:`~collections.abc.Collection` of :class:`str`;
146 or :data:`None`) optionally contains the path separators to
147 normalize. See :func:`~pathspec.util.normalize_file` for more
148 information.
150 Returns the matched entries (:class:`~collections.abc.Iterator` of
151 :class:`~util.TreeEntry`).
152 """
153 if not _is_iterable(entries):
154 raise TypeError(f"entries:{entries!r} is not an iterable.")
156 use_patterns = _filter_patterns(self.patterns)
157 for entry in entries:
158 norm_file = normalize_file(entry.path, separators)
159 if self._match_file(use_patterns, norm_file):
160 yield entry
162 # Match files using the `match_file()` utility function. Subclasses
163 # may override this method as an instance method. It does not have to
164 # be a static method.
165 _match_file = staticmethod(match_file)
167 def match_file(
168 self,
169 file: StrPath,
170 separators: Optional[Collection[str]] = None,
171 ) -> bool:
172 """
173 Matches the file to this path-spec.
175 *file* (:class:`str` or :class:`os.PathLike[str]`) is the file path to be
176 matched against :attr:`self.patterns <PathSpec.patterns>`.
178 *separators* (:class:`~collections.abc.Collection` of :class:`str`)
179 optionally contains the path separators to normalize. See
180 :func:`~pathspec.util.normalize_file` for more information.
182 Returns :data:`True` if *file* matched; otherwise, :data:`False`.
183 """
184 norm_file = util.normalize_file(file, separators=separators)
185 return self._match_file(self.patterns, norm_file)
187 def match_files(
188 self,
189 files: Iterable[StrPath],
190 separators: Optional[Collection[str]] = None,
191 ) -> Iterator[StrPath]:
192 """
193 Matches the files to this path-spec.
195 *files* (:class:`~collections.abc.Iterable` of :class:`str` or
196 :class:`os.PathLike[str]`) contains the file paths to be matched against
197 :attr:`self.patterns <PathSpec.patterns>`.
199 *separators* (:class:`~collections.abc.Collection` of :class:`str`;
200 or :data:`None`) optionally contains the path separators to
201 normalize. See :func:`~pathspec.util.normalize_file` for more
202 information.
204 Returns the matched files (:class:`~collections.abc.Iterator` of
205 :class:`str` or :class:`os.PathLike[str]`).
206 """
207 if not _is_iterable(files):
208 raise TypeError(f"files:{files!r} is not an iterable.")
210 use_patterns = _filter_patterns(self.patterns)
211 for orig_file in files:
212 norm_file = normalize_file(orig_file, separators)
213 if self._match_file(use_patterns, norm_file):
214 yield orig_file
216 def match_tree_entries(
217 self,
218 root: StrPath,
219 on_error: Optional[Callable] = None,
220 follow_links: Optional[bool] = None,
221 ) -> Iterator[TreeEntry]:
222 """
223 Walks the specified root path for all files and matches them to this
224 path-spec.
226 *root* (:class:`str` or :class:`os.PathLike[str]`) is the root directory
227 to search.
229 *on_error* (:class:`~collections.abc.Callable` or :data:`None`)
230 optionally is the error handler for file-system exceptions. See
231 :func:`~pathspec.util.iter_tree_entries` for more information.
233 *follow_links* (:class:`bool` or :data:`None`) optionally is whether
234 to walk symbolic links that resolve to directories. See
235 :func:`~pathspec.util.iter_tree_files` for more information.
237 Returns the matched files (:class:`~collections.abc.Iterator` of
238 :class:`.TreeEntry`).
239 """
240 entries = util.iter_tree_entries(root, on_error=on_error, follow_links=follow_links)
241 yield from self.match_entries(entries)
243 def match_tree_files(
244 self,
245 root: StrPath,
246 on_error: Optional[Callable] = None,
247 follow_links: Optional[bool] = None,
248 ) -> Iterator[str]:
249 """
250 Walks the specified root path for all files and matches them to this
251 path-spec.
253 *root* (:class:`str` or :class:`os.PathLike[str]`) is the root directory
254 to search for files.
256 *on_error* (:class:`~collections.abc.Callable` or :data:`None`)
257 optionally is the error handler for file-system exceptions. See
258 :func:`~pathspec.util.iter_tree_files` for more information.
260 *follow_links* (:class:`bool` or :data:`None`) optionally is whether
261 to walk symbolic links that resolve to directories. See
262 :func:`~pathspec.util.iter_tree_files` for more information.
264 Returns the matched files (:class:`~collections.abc.Iterable` of
265 :class:`str`).
266 """
267 files = util.iter_tree_files(root, on_error=on_error, follow_links=follow_links)
268 yield from self.match_files(files)
270 # Alias `match_tree_files()` as `match_tree()` for backward
271 # compatibility before v0.3.2.
272 match_tree = match_tree_files