Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pathspec/pattern.py: 38%
42 statements
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
1# encoding: utf-8
2"""
3This module provides the base definition for patterns.
4"""
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
20from .compat import unicode
23class Pattern(object):
24 """
25 The :class:`Pattern` class is the abstract definition of a pattern.
26 """
28 # Make the class dict-less.
29 __slots__ = ('include',)
31 def __init__(self, include):
32 # type: (Optional[bool]) -> None
33 """
34 Initializes the :class:`Pattern` instance.
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 """
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 """
48 def match(self, files):
49 # type: (Iterable[Text]) -> Iterator[Text]
50 """
51 Matches this pattern against the specified files.
53 *files* (:class:`~collections.abc.Iterable` of :class:`str`) contains
54 each file relative to the root directory (e.g., ``"relative/path/to/file"``).
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__))
62class RegexPattern(Pattern):
63 """
64 The :class:`RegexPattern` class is an implementation of a pattern
65 using regular expressions.
66 """
68 # Make the class dict-less.
69 __slots__ = ('regex',)
71 def __init__(self, pattern, include=None):
72 # type: (Union[AnyStr, RegexHint], Optional[bool]) -> None
73 """
74 Initializes the :class:`RegexPattern` instance.
76 *pattern* (:class:`unicode`, :class:`bytes`, :class:`re.RegexObject`,
77 or :data:`None`) is the pattern to compile into a regular
78 expression.
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`).
86 .. NOTE:: Subclasses do not need to support the *include*
87 parameter.
88 """
90 self.regex = None
91 """
92 *regex* (:class:`re.RegexObject`) is the regular expression for the
93 pattern.
94 """
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)
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
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)
114 else:
115 raise TypeError("pattern:{!r} is not a string, RegexObject, or None.".format(pattern))
117 super(RegexPattern, self).__init__(include)
118 self.regex = regex
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
132 def match(self, files):
133 # type: (Iterable[Text]) -> Iterable[Text]
134 """
135 Matches this pattern against the specified files.
137 *files* (:class:`~collections.abc.Iterable` of :class:`str`)
138 contains each file relative to the root directory (e.g., "relative/path/to/file").
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
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.
154 *pattern* (:class:`str`) is the pattern to convert into a regular
155 expression.
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`).
161 .. NOTE:: The default implementation simply returns *pattern* and
162 :data:`True`.
163 """
164 return pattern, True