Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pathspec/pathspec.py: 35%

69 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:35 +0000

1# encoding: utf-8 

2""" 

3This module provides an object oriented interface for pattern matching 

4of files. 

5""" 

6 

7try: 

8 from typing import ( 

9 Any, 

10 AnyStr, 

11 Callable, 

12 Iterable, 

13 Iterator, 

14 Optional, 

15 Text, 

16 Union) 

17except ImportError: 

18 pass 

19 

20try: 

21 # Python 3.6+ type hints. 

22 from os import PathLike 

23 from typing import Collection 

24except ImportError: 

25 pass 

26 

27from . import util 

28from .compat import ( 

29 CollectionType, 

30 iterkeys, 

31 izip_longest, 

32 string_types) 

33from .pattern import Pattern 

34from .util import TreeEntry 

35 

36 

37class PathSpec(object): 

38 """ 

39 The :class:`PathSpec` class is a wrapper around a list of compiled 

40 :class:`.Pattern` instances. 

41 """ 

42 

43 def __init__(self, patterns): 

44 # type: (Iterable[Pattern]) -> None 

45 """ 

46 Initializes the :class:`PathSpec` instance. 

47 

48 *patterns* (:class:`~collections.abc.Collection` or :class:`~collections.abc.Iterable`) 

49 yields each compiled pattern (:class:`.Pattern`). 

50 """ 

51 

52 self.patterns = patterns if isinstance(patterns, CollectionType) else list(patterns) 

53 """ 

54 *patterns* (:class:`~collections.abc.Collection` of :class:`.Pattern`) 

55 contains the compiled patterns. 

56 """ 

57 

58 def __eq__(self, other): 

59 # type: (PathSpec) -> bool 

60 """ 

61 Tests the equality of this path-spec with *other* (:class:`PathSpec`) 

62 by comparing their :attr:`~PathSpec.patterns` attributes. 

63 """ 

64 if isinstance(other, PathSpec): 

65 paired_patterns = izip_longest(self.patterns, other.patterns) 

66 return all(a == b for a, b in paired_patterns) 

67 else: 

68 return NotImplemented 

69 

70 def __len__(self): 

71 """ 

72 Returns the number of compiled patterns this path-spec contains 

73 (:class:`int`). 

74 """ 

75 return len(self.patterns) 

76 

77 def __add__(self, other): 

78 # type: (PathSpec) -> PathSpec 

79 """ 

80 Combines the :attr:`Pathspec.patterns` patterns from two 

81 :class:`PathSpec` instances. 

82 """ 

83 if isinstance(other, PathSpec): 

84 return PathSpec(self.patterns + other.patterns) 

85 else: 

86 return NotImplemented 

87 

88 def __iadd__(self, other): 

89 # type: (PathSpec) -> PathSpec 

90 """ 

91 Adds the :attr:`Pathspec.patterns` patterns from one :class:`PathSpec` 

92 instance to this instance. 

93 """ 

94 if isinstance(other, PathSpec): 

95 self.patterns += other.patterns 

96 return self 

97 else: 

98 return NotImplemented 

99 

100 @classmethod 

101 def from_lines(cls, pattern_factory, lines): 

102 # type: (Union[Text, Callable[[AnyStr], Pattern]], Iterable[AnyStr]) -> PathSpec 

103 """ 

104 Compiles the pattern lines. 

105 

106 *pattern_factory* can be either the name of a registered pattern 

107 factory (:class:`str`), or a :class:`~collections.abc.Callable` used 

108 to compile patterns. It must accept an uncompiled pattern (:class:`str`) 

109 and return the compiled pattern (:class:`.Pattern`). 

110 

111 *lines* (:class:`~collections.abc.Iterable`) yields each uncompiled 

112 pattern (:class:`str`). This simply has to yield each line so it can 

113 be a :class:`file` (e.g., from :func:`open` or :class:`io.StringIO`) 

114 or the result from :meth:`str.splitlines`. 

115 

116 Returns the :class:`PathSpec` instance. 

117 """ 

118 if isinstance(pattern_factory, string_types): 

119 pattern_factory = util.lookup_pattern(pattern_factory) 

120 if not callable(pattern_factory): 

121 raise TypeError("pattern_factory:{!r} is not callable.".format(pattern_factory)) 

122 

123 if not util._is_iterable(lines): 

124 raise TypeError("lines:{!r} is not an iterable.".format(lines)) 

125 

126 patterns = [pattern_factory(line) for line in lines if line] 

127 return cls(patterns) 

128 

129 def match_file(self, file, separators=None): 

130 # type: (Union[Text, PathLike], Optional[Collection[Text]]) -> bool 

131 """ 

132 Matches the file to this path-spec. 

133 

134 *file* (:class:`str` or :class:`~pathlib.PurePath`) is the file path 

135 to be matched against :attr:`self.patterns <PathSpec.patterns>`. 

136 

137 *separators* (:class:`~collections.abc.Collection` of :class:`str`) 

138 optionally contains the path separators to normalize. See 

139 :func:`~pathspec.util.normalize_file` for more information. 

140 

141 Returns :data:`True` if *file* matched; otherwise, :data:`False`. 

142 """ 

143 norm_file = util.normalize_file(file, separators=separators) 

144 return util.match_file(self.patterns, norm_file) 

145 

146 def match_entries(self, entries, separators=None): 

147 # type: (Iterable[TreeEntry], Optional[Collection[Text]]) -> Iterator[TreeEntry] 

148 """ 

149 Matches the entries to this path-spec. 

150 

151 *entries* (:class:`~collections.abc.Iterable` of :class:`~util.TreeEntry`) 

152 contains the entries to be matched against :attr:`self.patterns <PathSpec.patterns>`. 

153 

154 *separators* (:class:`~collections.abc.Collection` of :class:`str`; 

155 or :data:`None`) optionally contains the path separators to 

156 normalize. See :func:`~pathspec.util.normalize_file` for more 

157 information. 

158 

159 Returns the matched entries (:class:`~collections.abc.Iterator` of 

160 :class:`~util.TreeEntry`). 

161 """ 

162 if not util._is_iterable(entries): 

163 raise TypeError("entries:{!r} is not an iterable.".format(entries)) 

164 

165 entry_map = util._normalize_entries(entries, separators=separators) 

166 match_paths = util.match_files(self.patterns, iterkeys(entry_map)) 

167 for path in match_paths: 

168 yield entry_map[path] 

169 

170 def match_files(self, files, separators=None): 

171 # type: (Iterable[Union[Text, PathLike]], Optional[Collection[Text]]) -> Iterator[Union[Text, PathLike]] 

172 """ 

173 Matches the files to this path-spec. 

174 

175 *files* (:class:`~collections.abc.Iterable` of :class:`str; or 

176 :class:`pathlib.PurePath`) contains the file paths to be matched 

177 against :attr:`self.patterns <PathSpec.patterns>`. 

178 

179 *separators* (:class:`~collections.abc.Collection` of :class:`str`; 

180 or :data:`None`) optionally contains the path separators to 

181 normalize. See :func:`~pathspec.util.normalize_file` for more 

182 information. 

183 

184 Returns the matched files (:class:`~collections.abc.Iterator` of 

185 :class:`str` or :class:`pathlib.PurePath`). 

186 """ 

187 if not util._is_iterable(files): 

188 raise TypeError("files:{!r} is not an iterable.".format(files)) 

189 

190 file_map = util.normalize_files(files, separators=separators) 

191 matched_files = util.match_files(self.patterns, iterkeys(file_map)) 

192 for norm_file in matched_files: 

193 for orig_file in file_map[norm_file]: 

194 yield orig_file 

195 

196 def match_tree_entries(self, root, on_error=None, follow_links=None): 

197 # type: (Text, Optional[Callable], Optional[bool]) -> Iterator[TreeEntry] 

198 """ 

199 Walks the specified root path for all files and matches them to this 

200 path-spec. 

201 

202 *root* (:class:`str`; or :class:`pathlib.PurePath`) is the root 

203 directory to search. 

204 

205 *on_error* (:class:`~collections.abc.Callable` or :data:`None`) 

206 optionally is the error handler for file-system exceptions. See 

207 :func:`~pathspec.util.iter_tree_entries` for more information. 

208 

209 *follow_links* (:class:`bool` or :data:`None`) optionally is whether 

210 to walk symbolic links that resolve to directories. See 

211 :func:`~pathspec.util.iter_tree_files` for more information. 

212 

213 Returns the matched files (:class:`~collections.abc.Iterator` of 

214 :class:`.TreeEntry`). 

215 """ 

216 entries = util.iter_tree_entries(root, on_error=on_error, follow_links=follow_links) 

217 return self.match_entries(entries) 

218 

219 def match_tree_files(self, root, on_error=None, follow_links=None): 

220 # type: (Text, Optional[Callable], Optional[bool]) -> Iterator[Text] 

221 """ 

222 Walks the specified root path for all files and matches them to this 

223 path-spec. 

224 

225 *root* (:class:`str`; or :class:`pathlib.PurePath`) is the root 

226 directory to search for files. 

227 

228 *on_error* (:class:`~collections.abc.Callable` or :data:`None`) 

229 optionally is the error handler for file-system exceptions. See 

230 :func:`~pathspec.util.iter_tree_files` for more information. 

231 

232 *follow_links* (:class:`bool` or :data:`None`) optionally is whether 

233 to walk symbolic links that resolve to directories. See 

234 :func:`~pathspec.util.iter_tree_files` for more information. 

235 

236 Returns the matched files (:class:`~collections.abc.Iterable` of 

237 :class:`str`). 

238 """ 

239 files = util.iter_tree_files(root, on_error=on_error, follow_links=follow_links) 

240 return self.match_files(files) 

241 

242 # Alias `match_tree_files()` as `match_tree()`. 

243 match_tree = match_tree_files