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

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

53 statements  

1""" 

2This module provides :class:`.GitIgnoreSpec` which replicates 

3*.gitignore* behavior. 

4""" 

5 

6from typing import ( 

7 AnyStr, 

8 Callable, # Replaced by `collections.abc.Callable` in 3.9. 

9 Iterable, # Replaced by `collections.abc.Iterable` in 3.9. 

10 Optional, # Replaced by `X | None` in 3.10. 

11 Tuple, # Replaced by `tuple` in 3.9. 

12 Type, # Replaced by `type` in 3.9. 

13 TypeVar, 

14 Union, # Replaced by `X | Y` in 3.10. 

15 cast, 

16 overload) 

17 

18from .pathspec import ( 

19 PathSpec) 

20from .pattern import ( 

21 Pattern) 

22from .patterns.gitwildmatch import ( 

23 GitWildMatchPattern, 

24 _DIR_MARK) 

25from .util import ( 

26 _is_iterable) 

27 

28Self = TypeVar("Self", bound="GitIgnoreSpec") 

29""" 

30:class:`GitIgnoreSpec` self type hint to support Python v<3.11 using PEP 

31673 recommendation. 

32""" 

33 

34 

35class GitIgnoreSpec(PathSpec): 

36 """ 

37 The :class:`GitIgnoreSpec` class extends :class:`pathspec.pathspec.PathSpec` to 

38 replicate *.gitignore* behavior. 

39 """ 

40 

41 def __eq__(self, other: object) -> bool: 

42 """ 

43 Tests the equality of this gitignore-spec with *other* (:class:`GitIgnoreSpec`) 

44 by comparing their :attr:`~pathspec.pattern.Pattern` 

45 attributes. A non-:class:`GitIgnoreSpec` will not compare equal. 

46 """ 

47 if isinstance(other, GitIgnoreSpec): 

48 return super().__eq__(other) 

49 elif isinstance(other, PathSpec): 

50 return False 

51 else: 

52 return NotImplemented 

53 

54 # Support reversed order of arguments from PathSpec. 

55 @overload 

56 @classmethod 

57 def from_lines( 

58 cls: Type[Self], 

59 pattern_factory: Union[str, Callable[[AnyStr], Pattern]], 

60 lines: Iterable[AnyStr], 

61 ) -> Self: 

62 ... 

63 

64 @overload 

65 @classmethod 

66 def from_lines( 

67 cls: Type[Self], 

68 lines: Iterable[AnyStr], 

69 pattern_factory: Union[str, Callable[[AnyStr], Pattern], None] = None, 

70 ) -> Self: 

71 ... 

72 

73 @classmethod 

74 def from_lines( 

75 cls: Type[Self], 

76 lines: Iterable[AnyStr], 

77 pattern_factory: Union[str, Callable[[AnyStr], Pattern], None] = None, 

78 ) -> Self: 

79 """ 

80 Compiles the pattern lines. 

81 

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

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

84 be a :class:`io.TextIOBase` (e.g., from :func:`open` or 

85 :class:`io.StringIO`) or the result from :meth:`str.splitlines`. 

86 

87 *pattern_factory* can be :data:`None`, the name of a registered 

88 pattern factory (:class:`str`), or a :class:`~collections.abc.Callable` 

89 used to compile patterns. The callable must accept an uncompiled 

90 pattern (:class:`str`) and return the compiled pattern 

91 (:class:`pathspec.pattern.Pattern`). 

92 Default is :data:`None` for :class:`.GitWildMatchPattern`). 

93 

94 Returns the :class:`GitIgnoreSpec` instance. 

95 """ 

96 if pattern_factory is None: 

97 pattern_factory = GitWildMatchPattern 

98 

99 elif (isinstance(lines, (str, bytes)) or callable(lines)) and _is_iterable(pattern_factory): 

100 # Support reversed order of arguments from PathSpec. 

101 pattern_factory, lines = lines, pattern_factory 

102 

103 self = super().from_lines(pattern_factory, lines) 

104 return cast(Self, self) 

105 

106 @staticmethod 

107 def _match_file( 

108 patterns: Iterable[Tuple[int, GitWildMatchPattern]], 

109 file: str, 

110 ) -> Tuple[Optional[bool], Optional[int]]: 

111 """ 

112 Check the file against the patterns. 

113 

114 .. NOTE:: Subclasses of :class:`~pathspec.pathspec.PathSpec` may override 

115 this method as an instance method. It does not have to be a static 

116 method. The signature for this method is subject to change. 

117 

118 *patterns* (:class:`~collections.abc.Iterable`) yields each indexed pattern 

119 (:class:`tuple`) which contains the pattern index (:class:`int`) and actual 

120 pattern (:class:`~pathspec.pattern.Pattern`). 

121 

122 *file* (:class:`str`) is the normalized file path to be matched against 

123 *patterns*. 

124 

125 Returns a :class:`tuple` containing whether to include *file* (:class:`bool` 

126 or :data:`None`), and the index of the last matched pattern (:class:`int` or 

127 :data:`None`). 

128 """ 

129 out_include: Optional[bool] = None 

130 out_index: Optional[int] = None 

131 out_priority = 0 

132 for index, pattern in patterns: 

133 if pattern.include is not None: 

134 match = pattern.match_file(file) 

135 if match is not None: 

136 # Pattern matched. 

137 

138 # Check for directory marker. 

139 dir_mark = match.match.groupdict().get(_DIR_MARK) 

140 

141 if dir_mark: 

142 # Pattern matched by a directory pattern. 

143 priority = 1 

144 else: 

145 # Pattern matched by a file pattern. 

146 priority = 2 

147 

148 if pattern.include and dir_mark: 

149 out_include = pattern.include 

150 out_index = index 

151 out_priority = priority 

152 elif priority >= out_priority: 

153 out_include = pattern.include 

154 out_index = index 

155 out_priority = priority 

156 

157 return out_include, out_index