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

43 statements  

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

1""" 

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

3*.gitignore* behavior. 

4""" 

5 

6from typing import ( 

7 AnyStr, 

8 Callable, 

9 Collection, 

10 Iterable, 

11 Type, 

12 TypeVar, 

13 Union) 

14 

15from .pathspec import ( 

16 PathSpec) 

17from .pattern import ( 

18 Pattern) 

19from .patterns.gitwildmatch import ( 

20 GitWildMatchPattern, 

21 GitWildMatchPatternError, 

22 _DIR_MARK) 

23from .util import ( 

24 _is_iterable) 

25 

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

27""" 

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

29673 recommendation. 

30""" 

31 

32 

33class GitIgnoreSpec(PathSpec): 

34 """ 

35 The :class:`GitIgnoreSpec` class extends :class:`PathSpec` to 

36 replicate *.gitignore* behavior. 

37 """ 

38 

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

40 """ 

41 Tests the equality of this gitignore-spec with *other* 

42 (:class:`GitIgnoreSpec`) by comparing their :attr:`~PathSpec.patterns` 

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

44 """ 

45 if isinstance(other, GitIgnoreSpec): 

46 return super().__eq__(other) 

47 elif isinstance(other, PathSpec): 

48 return False 

49 else: 

50 return NotImplemented 

51 

52 @classmethod 

53 def from_lines( 

54 cls: Type[Self], 

55 lines: Iterable[AnyStr], 

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

57 ) -> Self: 

58 """ 

59 Compiles the pattern lines. 

60 

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

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

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

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

65 

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

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

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

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

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

71 

72 Returns the :class:`GitIgnoreSpec` instance. 

73 """ 

74 if pattern_factory is None: 

75 pattern_factory = GitWildMatchPattern 

76 

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

78 # Support reversed order of arguments from PathSpec. 

79 pattern_factory, lines = lines, pattern_factory 

80 

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

82 return self # type: ignore 

83 

84 @staticmethod 

85 def _match_file( 

86 patterns: Collection[GitWildMatchPattern], 

87 file: str, 

88 ) -> bool: 

89 """ 

90 Matches the file to the patterns. 

91 

92 .. NOTE:: Subclasses of :class:`.PathSpec` may override this 

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

94 method. 

95 

96 *patterns* (:class:`~collections.abc.Iterable` of :class:`~pathspec.pattern.Pattern`) 

97 contains the patterns to use. 

98 

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

100 against *patterns*. 

101 

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

103 """ 

104 out_matched = False 

105 out_priority = 0 

106 for pattern in patterns: 

107 if pattern.include is not None: 

108 match = pattern.match_file(file) 

109 if match is not None: 

110 # Pattern matched. 

111 

112 # Check for directory marker. 

113 try: 

114 dir_mark = match.match.group(_DIR_MARK) 

115 except IndexError as e: 

116 # NOTICE: The exact content of this error message is subject 

117 # to change. 

118 raise GitWildMatchPatternError(( 

119 f"Invalid git pattern: directory marker regex group is missing. " 

120 f"Debug: file={file!r} regex={pattern.regex!r} " 

121 f"group={_DIR_MARK!r} match={match.match!r}." 

122 )) from e 

123 

124 if dir_mark: 

125 # Pattern matched by a directory pattern. 

126 priority = 1 

127 else: 

128 # Pattern matched by a file pattern. 

129 priority = 2 

130 

131 if pattern.include and dir_mark: 

132 out_matched = pattern.include 

133 out_priority = priority 

134 elif priority >= out_priority: 

135 out_matched = pattern.include 

136 out_priority = priority 

137 

138 return out_matched