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

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

48 statements  

1""" 

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

3behavior, and handles edge-cases where Git's behavior differs from what's 

4documented. Git allows including files from excluded directories which directly 

5contradicts the documentation. This uses :class:`.GitIgnoreSpecPattern` to fully 

6replicate Git's handling. 

7""" 

8from __future__ import annotations 

9 

10from collections.abc import ( 

11 Iterable, 

12 Sequence) 

13from typing import ( 

14 Callable, # Replaced by `collections.abc.Callable` in 3.9.2. 

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

16 TypeVar, 

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

18 cast, 

19 overload) 

20 

21from pathspec.backend import ( 

22 BackendNamesHint, 

23 _Backend) 

24from pathspec._backends.agg import ( 

25 make_gitignore_backend) 

26from pathspec.pathspec import ( 

27 PathSpec) 

28from pathspec.pattern import ( 

29 Pattern) 

30from pathspec.patterns.gitignore.basic import ( 

31 GitIgnoreBasicPattern) 

32from pathspec.patterns.gitignore.spec import ( 

33 GitIgnoreSpecPattern) 

34from pathspec._typing import ( 

35 AnyStr, # Removed in 3.18. 

36 override) # Added in 3.12. 

37from pathspec.util import ( 

38 _is_iterable, 

39 lookup_pattern) 

40 

41Self = TypeVar("Self", bound='GitIgnoreSpec') 

42""" 

43:class:`.GitIgnoreSpec` self type hint to support Python v<3.11 using PEP 673 

44recommendation. 

45""" 

46 

47 

48class GitIgnoreSpec(PathSpec): 

49 """ 

50 The :class:`GitIgnoreSpec` class extends :class:`.PathSpec` to replicate 

51 *gitignore* behavior. This is uses :class:`.GitIgnoreSpecPattern` to fully 

52 replicate Git's handling. 

53 """ 

54 

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

56 """ 

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

58 by comparing their :attr:`self.patterns <.PathSpec.patterns>` attributes. A 

59 non-:class:`GitIgnoreSpec` will not compare equal. 

60 """ 

61 if isinstance(other, GitIgnoreSpec): 

62 return super().__eq__(other) 

63 elif isinstance(other, PathSpec): 

64 return False 

65 else: 

66 return NotImplemented 

67 

68 # Support reversed order of arguments from PathSpec. 

69 @overload 

70 @classmethod 

71 def from_lines( 

72 cls: type[Self], 

73 pattern_factory: Union[str, Callable[[AnyStr], Pattern], None], 

74 lines: Iterable[AnyStr], 

75 *, 

76 backend: Union[BackendNamesHint, str, None] = None, 

77 _test_backend_factory: Optional[Callable[[Sequence[Pattern]], _Backend]] = None, 

78 ) -> Self: 

79 ... 

80 

81 @overload 

82 @classmethod 

83 def from_lines( 

84 cls: type[Self], 

85 lines: Iterable[AnyStr], 

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

87 *, 

88 backend: Union[BackendNamesHint, str, None] = None, 

89 _test_backend_factory: Optional[Callable[[Sequence[Pattern]], _Backend]] = None, 

90 ) -> Self: 

91 ... 

92 

93 @override 

94 @classmethod 

95 def from_lines( 

96 cls: type[Self], 

97 lines: Iterable[AnyStr], 

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

99 *, 

100 backend: Union[BackendNamesHint, str, None] = None, 

101 _test_backend_factory: Optional[Callable[[Sequence[Pattern]], _Backend]] = None, 

102 ) -> Self: 

103 """ 

104 Compiles the pattern lines. 

105 

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

107 (:class:`str`). This simply has to yield each line, so it can be a 

108 :class:`io.TextIOBase` (e.g., from :func:`open` or :class:`io.StringIO`) or 

109 the result from :meth:`str.splitlines`. 

110 

111 *pattern_factory* does not need to be set for :class:`GitIgnoreSpec`. If 

112 set, it should be either ``"gitignore"`` or :class:`.GitIgnoreSpecPattern`. 

113 There is no guarantee it will work with any other pattern class. Default is 

114 :data:`None` for :class:`.GitIgnoreSpecPattern`. 

115 

116 *backend* (:class:`str` or :data:`None`) is the pattern (regular expression) 

117 matching backend to use. Default is :data:`None` for "best" to use the best 

118 available backend. Priority of backends is: "re2", "hyperscan", "simple". 

119 The "simple" backend is always available. 

120 

121 Returns the :class:`GitIgnoreSpec` instance. 

122 """ 

123 if (isinstance(lines, (str, bytes)) or callable(lines)) and _is_iterable(pattern_factory): 

124 # Support reversed order of arguments from PathSpec. 

125 pattern_factory, lines = lines, pattern_factory 

126 

127 if pattern_factory is None: 

128 pattern_factory = GitIgnoreSpecPattern 

129 elif pattern_factory == 'gitignore': 

130 # Force use of GitIgnoreSpecPattern for "gitignore" to handle edge-cases. 

131 # This makes usage easier. 

132 pattern_factory = GitIgnoreSpecPattern 

133 

134 if isinstance(pattern_factory, str): 

135 pattern_factory = lookup_pattern(pattern_factory) 

136 

137 if issubclass(pattern_factory, GitIgnoreBasicPattern): 

138 raise TypeError(( 

139 f"{pattern_factory=!r} cannot be {GitIgnoreBasicPattern} because it " 

140 f"will give unexpected results." 

141 )) # TypeError 

142 

143 self = super().from_lines(pattern_factory, lines, backend=backend, _test_backend_factory=_test_backend_factory) 

144 return cast(Self, self) 

145 

146 @override 

147 @staticmethod 

148 def _make_backend( 

149 name: BackendNamesHint, 

150 patterns: Sequence[Pattern], 

151 ) -> _Backend: 

152 """ 

153 .. warning:: This method is not part of the public API. It is subject to 

154 change. 

155 

156 Create the backend for the patterns. 

157 

158 *name* (:class:`str`) is the name of the backend. 

159 

160 *patterns* (:class:`~collections.abc.Sequence` of :class:`.Pattern`) 

161 contains the compiled patterns. 

162 

163 Returns the backend (:class:`._Backend`). 

164 """ 

165 return make_gitignore_backend(name, patterns)