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

42 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 the base definition for patterns. 

4""" 

5 

6import re 

7try: 

8 from typing import ( 

9 AnyStr, 

10 Iterable, 

11 Iterator, 

12 Optional, 

13 Pattern as RegexHint, 

14 Text, 

15 Tuple, 

16 Union) 

17except ImportError: 

18 pass 

19 

20from .compat import unicode 

21 

22 

23class Pattern(object): 

24 """ 

25 The :class:`Pattern` class is the abstract definition of a pattern. 

26 """ 

27 

28 # Make the class dict-less. 

29 __slots__ = ('include',) 

30 

31 def __init__(self, include): 

32 # type: (Optional[bool]) -> None 

33 """ 

34 Initializes the :class:`Pattern` instance. 

35 

36 *include* (:class:`bool` or :data:`None`) is whether the matched 

37 files should be included (:data:`True`), excluded (:data:`False`), 

38 or is a null-operation (:data:`None`). 

39 """ 

40 

41 self.include = include 

42 """ 

43 *include* (:class:`bool` or :data:`None`) is whether the matched 

44 files should be included (:data:`True`), excluded (:data:`False`), 

45 or is a null-operation (:data:`None`). 

46 """ 

47 

48 def match(self, files): 

49 # type: (Iterable[Text]) -> Iterator[Text] 

50 """ 

51 Matches this pattern against the specified files. 

52 

53 *files* (:class:`~collections.abc.Iterable` of :class:`str`) contains 

54 each file relative to the root directory (e.g., ``"relative/path/to/file"``). 

55 

56 Returns an :class:`~collections.abc.Iterable` yielding each matched 

57 file path (:class:`str`). 

58 """ 

59 raise NotImplementedError("{}.{} must override match().".format(self.__class__.__module__, self.__class__.__name__)) 

60 

61 

62class RegexPattern(Pattern): 

63 """ 

64 The :class:`RegexPattern` class is an implementation of a pattern 

65 using regular expressions. 

66 """ 

67 

68 # Make the class dict-less. 

69 __slots__ = ('regex',) 

70 

71 def __init__(self, pattern, include=None): 

72 # type: (Union[AnyStr, RegexHint], Optional[bool]) -> None 

73 """ 

74 Initializes the :class:`RegexPattern` instance. 

75 

76 *pattern* (:class:`unicode`, :class:`bytes`, :class:`re.RegexObject`, 

77 or :data:`None`) is the pattern to compile into a regular 

78 expression. 

79 

80 *include* (:class:`bool` or :data:`None`) must be :data:`None` 

81 unless *pattern* is a precompiled regular expression (:class:`re.RegexObject`) 

82 in which case it is whether matched files should be included 

83 (:data:`True`), excluded (:data:`False`), or is a null operation 

84 (:data:`None`). 

85 

86 .. NOTE:: Subclasses do not need to support the *include* 

87 parameter. 

88 """ 

89 

90 self.regex = None 

91 """ 

92 *regex* (:class:`re.RegexObject`) is the regular expression for the 

93 pattern. 

94 """ 

95 

96 if isinstance(pattern, (unicode, bytes)): 

97 assert include is None, "include:{!r} must be null when pattern:{!r} is a string.".format(include, pattern) 

98 regex, include = self.pattern_to_regex(pattern) 

99 # NOTE: Make sure to allow a null regular expression to be 

100 # returned for a null-operation. 

101 if include is not None: 

102 regex = re.compile(regex) 

103 

104 elif pattern is not None and hasattr(pattern, 'match'): 

105 # Assume pattern is a precompiled regular expression. 

106 # - NOTE: Used specified *include*. 

107 regex = pattern 

108 

109 elif pattern is None: 

110 # NOTE: Make sure to allow a null pattern to be passed for a 

111 # null-operation. 

112 assert include is None, "include:{!r} must be null when pattern:{!r} is null.".format(include, pattern) 

113 

114 else: 

115 raise TypeError("pattern:{!r} is not a string, RegexObject, or None.".format(pattern)) 

116 

117 super(RegexPattern, self).__init__(include) 

118 self.regex = regex 

119 

120 def __eq__(self, other): 

121 # type: (RegexPattern) -> bool 

122 """ 

123 Tests the equality of this regex pattern with *other* (:class:`RegexPattern`) 

124 by comparing their :attr:`~Pattern.include` and :attr:`~RegexPattern.regex` 

125 attributes. 

126 """ 

127 if isinstance(other, RegexPattern): 

128 return self.include == other.include and self.regex == other.regex 

129 else: 

130 return NotImplemented 

131 

132 def match(self, files): 

133 # type: (Iterable[Text]) -> Iterable[Text] 

134 """ 

135 Matches this pattern against the specified files. 

136 

137 *files* (:class:`~collections.abc.Iterable` of :class:`str`) 

138 contains each file relative to the root directory (e.g., "relative/path/to/file"). 

139 

140 Returns an :class:`~collections.abc.Iterable` yielding each matched 

141 file path (:class:`str`). 

142 """ 

143 if self.include is not None: 

144 for path in files: 

145 if self.regex.match(path) is not None: 

146 yield path 

147 

148 @classmethod 

149 def pattern_to_regex(cls, pattern): 

150 # type: (Text) -> Tuple[Text, bool] 

151 """ 

152 Convert the pattern into an uncompiled regular expression. 

153 

154 *pattern* (:class:`str`) is the pattern to convert into a regular 

155 expression. 

156 

157 Returns the uncompiled regular expression (:class:`str` or :data:`None`), 

158 and whether matched files should be included (:data:`True`), 

159 excluded (:data:`False`), or is a null-operation (:data:`None`). 

160 

161 .. NOTE:: The default implementation simply returns *pattern* and 

162 :data:`True`. 

163 """ 

164 return pattern, True