pytester: LineMatcher: typing, docs, consecutive line matching (#6653)
This commit is contained in:
		
						commit
						39d9f7cff5
					
				| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					Add support for matching lines consecutively with :attr:`LineMatcher <_pytest.pytester.LineMatcher>`'s :func:`~_pytest.pytester.LineMatcher.fnmatch_lines` and :func:`~_pytest.pytester.LineMatcher.re_match_lines`.
 | 
				
			||||||
| 
						 | 
					@ -413,8 +413,8 @@ class RunResult:
 | 
				
			||||||
    def __init__(
 | 
					    def __init__(
 | 
				
			||||||
        self,
 | 
					        self,
 | 
				
			||||||
        ret: Union[int, ExitCode],
 | 
					        ret: Union[int, ExitCode],
 | 
				
			||||||
        outlines: Sequence[str],
 | 
					        outlines: List[str],
 | 
				
			||||||
        errlines: Sequence[str],
 | 
					        errlines: List[str],
 | 
				
			||||||
        duration: float,
 | 
					        duration: float,
 | 
				
			||||||
    ) -> None:
 | 
					    ) -> None:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
| 
						 | 
					@ -1318,49 +1318,32 @@ class LineMatcher:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    The constructor takes a list of lines without their trailing newlines, i.e.
 | 
					    The constructor takes a list of lines without their trailing newlines, i.e.
 | 
				
			||||||
    ``text.splitlines()``.
 | 
					    ``text.splitlines()``.
 | 
				
			||||||
 | 
					 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, lines):
 | 
					    def __init__(self, lines: List[str]) -> None:
 | 
				
			||||||
        self.lines = lines
 | 
					        self.lines = lines
 | 
				
			||||||
        self._log_output = []
 | 
					        self._log_output = []  # type: List[str]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def str(self):
 | 
					    def _getlines(self, lines2: Union[str, Sequence[str], Source]) -> Sequence[str]:
 | 
				
			||||||
        """Return the entire original text."""
 | 
					 | 
				
			||||||
        return "\n".join(self.lines)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _getlines(self, lines2):
 | 
					 | 
				
			||||||
        if isinstance(lines2, str):
 | 
					        if isinstance(lines2, str):
 | 
				
			||||||
            lines2 = Source(lines2)
 | 
					            lines2 = Source(lines2)
 | 
				
			||||||
        if isinstance(lines2, Source):
 | 
					        if isinstance(lines2, Source):
 | 
				
			||||||
            lines2 = lines2.strip().lines
 | 
					            lines2 = lines2.strip().lines
 | 
				
			||||||
        return lines2
 | 
					        return lines2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def fnmatch_lines_random(self, lines2):
 | 
					    def fnmatch_lines_random(self, lines2: Sequence[str]) -> None:
 | 
				
			||||||
        """Check lines exist in the output using in any order.
 | 
					        """Check lines exist in the output in any order (using :func:`python:fnmatch.fnmatch`).
 | 
				
			||||||
 | 
					 | 
				
			||||||
        Lines are checked using ``fnmatch.fnmatch``. The argument is a list of
 | 
					 | 
				
			||||||
        lines which have to occur in the output, in any order.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        self._match_lines_random(lines2, fnmatch)
 | 
					        self._match_lines_random(lines2, fnmatch)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def re_match_lines_random(self, lines2):
 | 
					    def re_match_lines_random(self, lines2: Sequence[str]) -> None:
 | 
				
			||||||
        """Check lines exist in the output using ``re.match``, in any order.
 | 
					        """Check lines exist in the output in any order (using :func:`python:re.match`).
 | 
				
			||||||
 | 
					 | 
				
			||||||
        The argument is a list of lines which have to occur in the output, in
 | 
					 | 
				
			||||||
        any order.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        self._match_lines_random(lines2, lambda name, pat: re.match(pat, name))
 | 
					        self._match_lines_random(lines2, lambda name, pat: bool(re.match(pat, name)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _match_lines_random(self, lines2, match_func):
 | 
					    def _match_lines_random(
 | 
				
			||||||
        """Check lines exist in the output.
 | 
					        self, lines2: Sequence[str], match_func: Callable[[str, str], bool]
 | 
				
			||||||
 | 
					    ) -> None:
 | 
				
			||||||
        The argument is a list of lines which have to occur in the output, in
 | 
					 | 
				
			||||||
        any order.  Each line can contain glob whildcards.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        lines2 = self._getlines(lines2)
 | 
					        lines2 = self._getlines(lines2)
 | 
				
			||||||
        for line in lines2:
 | 
					        for line in lines2:
 | 
				
			||||||
            for x in self.lines:
 | 
					            for x in self.lines:
 | 
				
			||||||
| 
						 | 
					@ -1371,46 +1354,67 @@ class LineMatcher:
 | 
				
			||||||
                self._log("line %r not found in output" % line)
 | 
					                self._log("line %r not found in output" % line)
 | 
				
			||||||
                raise ValueError(self._log_text)
 | 
					                raise ValueError(self._log_text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_lines_after(self, fnline):
 | 
					    def get_lines_after(self, fnline: str) -> Sequence[str]:
 | 
				
			||||||
        """Return all lines following the given line in the text.
 | 
					        """Return all lines following the given line in the text.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        The given line can contain glob wildcards.
 | 
					        The given line can contain glob wildcards.
 | 
				
			||||||
 | 
					 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        for i, line in enumerate(self.lines):
 | 
					        for i, line in enumerate(self.lines):
 | 
				
			||||||
            if fnline == line or fnmatch(line, fnline):
 | 
					            if fnline == line or fnmatch(line, fnline):
 | 
				
			||||||
                return self.lines[i + 1 :]
 | 
					                return self.lines[i + 1 :]
 | 
				
			||||||
        raise ValueError("line %r not found in output" % fnline)
 | 
					        raise ValueError("line %r not found in output" % fnline)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _log(self, *args):
 | 
					    def _log(self, *args) -> None:
 | 
				
			||||||
        self._log_output.append(" ".join(str(x) for x in args))
 | 
					        self._log_output.append(" ".join(str(x) for x in args))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def _log_text(self):
 | 
					    def _log_text(self) -> str:
 | 
				
			||||||
        return "\n".join(self._log_output)
 | 
					        return "\n".join(self._log_output)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def fnmatch_lines(self, lines2):
 | 
					    def fnmatch_lines(
 | 
				
			||||||
        """Search captured text for matching lines using ``fnmatch.fnmatch``.
 | 
					        self, lines2: Sequence[str], *, consecutive: bool = False
 | 
				
			||||||
 | 
					    ) -> None:
 | 
				
			||||||
 | 
					        """Check lines exist in the output (using :func:`python:fnmatch.fnmatch`).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        The argument is a list of lines which have to match and can use glob
 | 
					        The argument is a list of lines which have to match and can use glob
 | 
				
			||||||
        wildcards.  If they do not match a pytest.fail() is called.  The
 | 
					        wildcards.  If they do not match a pytest.fail() is called.  The
 | 
				
			||||||
        matches and non-matches are also shown as part of the error message.
 | 
					        matches and non-matches are also shown as part of the error message.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param lines2: string patterns to match.
 | 
				
			||||||
 | 
					        :param consecutive: match lines consecutive?
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        __tracebackhide__ = True
 | 
					        __tracebackhide__ = True
 | 
				
			||||||
        self._match_lines(lines2, fnmatch, "fnmatch")
 | 
					        self._match_lines(lines2, fnmatch, "fnmatch", consecutive=consecutive)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def re_match_lines(self, lines2):
 | 
					    def re_match_lines(
 | 
				
			||||||
        """Search captured text for matching lines using ``re.match``.
 | 
					        self, lines2: Sequence[str], *, consecutive: bool = False
 | 
				
			||||||
 | 
					    ) -> None:
 | 
				
			||||||
 | 
					        """Check lines exist in the output (using :func:`python:re.match`).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        The argument is a list of lines which have to match using ``re.match``.
 | 
					        The argument is a list of lines which have to match using ``re.match``.
 | 
				
			||||||
        If they do not match a pytest.fail() is called.
 | 
					        If they do not match a pytest.fail() is called.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        The matches and non-matches are also shown as part of the error message.
 | 
					        The matches and non-matches are also shown as part of the error message.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :param lines2: string patterns to match.
 | 
				
			||||||
 | 
					        :param consecutive: match lines consecutively?
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        __tracebackhide__ = True
 | 
					        __tracebackhide__ = True
 | 
				
			||||||
        self._match_lines(lines2, lambda name, pat: re.match(pat, name), "re.match")
 | 
					        self._match_lines(
 | 
				
			||||||
 | 
					            lines2,
 | 
				
			||||||
 | 
					            lambda name, pat: bool(re.match(pat, name)),
 | 
				
			||||||
 | 
					            "re.match",
 | 
				
			||||||
 | 
					            consecutive=consecutive,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _match_lines(self, lines2, match_func, match_nickname):
 | 
					    def _match_lines(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        lines2: Sequence[str],
 | 
				
			||||||
 | 
					        match_func: Callable[[str, str], bool],
 | 
				
			||||||
 | 
					        match_nickname: str,
 | 
				
			||||||
 | 
					        *,
 | 
				
			||||||
 | 
					        consecutive: bool = False
 | 
				
			||||||
 | 
					    ) -> None:
 | 
				
			||||||
        """Underlying implementation of ``fnmatch_lines`` and ``re_match_lines``.
 | 
					        """Underlying implementation of ``fnmatch_lines`` and ``re_match_lines``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :param list[str] lines2: list of string patterns to match. The actual
 | 
					        :param list[str] lines2: list of string patterns to match. The actual
 | 
				
			||||||
| 
						 | 
					@ -1420,28 +1424,40 @@ class LineMatcher:
 | 
				
			||||||
            pattern
 | 
					            pattern
 | 
				
			||||||
        :param str match_nickname: the nickname for the match function that
 | 
					        :param str match_nickname: the nickname for the match function that
 | 
				
			||||||
            will be logged to stdout when a match occurs
 | 
					            will be logged to stdout when a match occurs
 | 
				
			||||||
 | 
					        :param consecutive: match lines consecutively?
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        assert isinstance(lines2, collections.abc.Sequence)
 | 
					        if not isinstance(lines2, collections.abc.Sequence):
 | 
				
			||||||
 | 
					            raise TypeError("invalid type for lines2: {}".format(type(lines2).__name__))
 | 
				
			||||||
        lines2 = self._getlines(lines2)
 | 
					        lines2 = self._getlines(lines2)
 | 
				
			||||||
        lines1 = self.lines[:]
 | 
					        lines1 = self.lines[:]
 | 
				
			||||||
        nextline = None
 | 
					        nextline = None
 | 
				
			||||||
        extralines = []
 | 
					        extralines = []
 | 
				
			||||||
        __tracebackhide__ = True
 | 
					        __tracebackhide__ = True
 | 
				
			||||||
        wnick = len(match_nickname) + 1
 | 
					        wnick = len(match_nickname) + 1
 | 
				
			||||||
 | 
					        started = False
 | 
				
			||||||
        for line in lines2:
 | 
					        for line in lines2:
 | 
				
			||||||
            nomatchprinted = False
 | 
					            nomatchprinted = False
 | 
				
			||||||
            while lines1:
 | 
					            while lines1:
 | 
				
			||||||
                nextline = lines1.pop(0)
 | 
					                nextline = lines1.pop(0)
 | 
				
			||||||
                if line == nextline:
 | 
					                if line == nextline:
 | 
				
			||||||
                    self._log("exact match:", repr(line))
 | 
					                    self._log("exact match:", repr(line))
 | 
				
			||||||
 | 
					                    started = True
 | 
				
			||||||
                    break
 | 
					                    break
 | 
				
			||||||
                elif match_func(nextline, line):
 | 
					                elif match_func(nextline, line):
 | 
				
			||||||
                    self._log("%s:" % match_nickname, repr(line))
 | 
					                    self._log("%s:" % match_nickname, repr(line))
 | 
				
			||||||
                    self._log(
 | 
					                    self._log(
 | 
				
			||||||
                        "{:>{width}}".format("with:", width=wnick), repr(nextline)
 | 
					                        "{:>{width}}".format("with:", width=wnick), repr(nextline)
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
 | 
					                    started = True
 | 
				
			||||||
                    break
 | 
					                    break
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
 | 
					                    if consecutive and started:
 | 
				
			||||||
 | 
					                        msg = "no consecutive match: {!r}".format(line)
 | 
				
			||||||
 | 
					                        self._log(msg)
 | 
				
			||||||
 | 
					                        self._log(
 | 
				
			||||||
 | 
					                            "{:>{width}}".format("with:", width=wnick), repr(nextline)
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                        self._fail(msg)
 | 
				
			||||||
                    if not nomatchprinted:
 | 
					                    if not nomatchprinted:
 | 
				
			||||||
                        self._log(
 | 
					                        self._log(
 | 
				
			||||||
                            "{:>{width}}".format("nomatch:", width=wnick), repr(line)
 | 
					                            "{:>{width}}".format("nomatch:", width=wnick), repr(line)
 | 
				
			||||||
| 
						 | 
					@ -1455,7 +1471,7 @@ class LineMatcher:
 | 
				
			||||||
                self._fail(msg)
 | 
					                self._fail(msg)
 | 
				
			||||||
        self._log_output = []
 | 
					        self._log_output = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def no_fnmatch_line(self, pat):
 | 
					    def no_fnmatch_line(self, pat: str) -> None:
 | 
				
			||||||
        """Ensure captured lines do not match the given pattern, using ``fnmatch.fnmatch``.
 | 
					        """Ensure captured lines do not match the given pattern, using ``fnmatch.fnmatch``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :param str pat: the pattern to match lines.
 | 
					        :param str pat: the pattern to match lines.
 | 
				
			||||||
| 
						 | 
					@ -1463,15 +1479,19 @@ class LineMatcher:
 | 
				
			||||||
        __tracebackhide__ = True
 | 
					        __tracebackhide__ = True
 | 
				
			||||||
        self._no_match_line(pat, fnmatch, "fnmatch")
 | 
					        self._no_match_line(pat, fnmatch, "fnmatch")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def no_re_match_line(self, pat):
 | 
					    def no_re_match_line(self, pat: str) -> None:
 | 
				
			||||||
        """Ensure captured lines do not match the given pattern, using ``re.match``.
 | 
					        """Ensure captured lines do not match the given pattern, using ``re.match``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :param str pat: the regular expression to match lines.
 | 
					        :param str pat: the regular expression to match lines.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        __tracebackhide__ = True
 | 
					        __tracebackhide__ = True
 | 
				
			||||||
        self._no_match_line(pat, lambda name, pat: re.match(pat, name), "re.match")
 | 
					        self._no_match_line(
 | 
				
			||||||
 | 
					            pat, lambda name, pat: bool(re.match(pat, name)), "re.match"
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _no_match_line(self, pat, match_func, match_nickname):
 | 
					    def _no_match_line(
 | 
				
			||||||
 | 
					        self, pat: str, match_func: Callable[[str, str], bool], match_nickname: str
 | 
				
			||||||
 | 
					    ) -> None:
 | 
				
			||||||
        """Ensure captured lines does not have a the given pattern, using ``fnmatch.fnmatch``
 | 
					        """Ensure captured lines does not have a the given pattern, using ``fnmatch.fnmatch``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :param str pat: the pattern to match lines
 | 
					        :param str pat: the pattern to match lines
 | 
				
			||||||
| 
						 | 
					@ -1492,8 +1512,12 @@ class LineMatcher:
 | 
				
			||||||
                self._log("{:>{width}}".format("and:", width=wnick), repr(line))
 | 
					                self._log("{:>{width}}".format("and:", width=wnick), repr(line))
 | 
				
			||||||
        self._log_output = []
 | 
					        self._log_output = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _fail(self, msg):
 | 
					    def _fail(self, msg: str) -> None:
 | 
				
			||||||
        __tracebackhide__ = True
 | 
					        __tracebackhide__ = True
 | 
				
			||||||
        log_text = self._log_text
 | 
					        log_text = self._log_text
 | 
				
			||||||
        self._log_output = []
 | 
					        self._log_output = []
 | 
				
			||||||
        pytest.fail(log_text)
 | 
					        pytest.fail(log_text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def str(self) -> str:
 | 
				
			||||||
 | 
					        """Return the entire original text."""
 | 
				
			||||||
 | 
					        return "\n".join(self.lines)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -458,17 +458,26 @@ def test_testdir_run_timeout_expires(testdir) -> None:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_linematcher_with_nonlist() -> None:
 | 
					def test_linematcher_with_nonlist() -> None:
 | 
				
			||||||
    """Test LineMatcher with regard to passing in a set (accidentally)."""
 | 
					    """Test LineMatcher with regard to passing in a set (accidentally)."""
 | 
				
			||||||
    lm = LineMatcher([])
 | 
					    from _pytest._code.source import Source
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with pytest.raises(AssertionError):
 | 
					    lm = LineMatcher([])
 | 
				
			||||||
        lm.fnmatch_lines(set())
 | 
					    with pytest.raises(TypeError, match="invalid type for lines2: set"):
 | 
				
			||||||
    with pytest.raises(AssertionError):
 | 
					        lm.fnmatch_lines(set())  # type: ignore[arg-type]  # noqa: F821
 | 
				
			||||||
        lm.fnmatch_lines({})
 | 
					    with pytest.raises(TypeError, match="invalid type for lines2: dict"):
 | 
				
			||||||
 | 
					        lm.fnmatch_lines({})  # type: ignore[arg-type]  # noqa: F821
 | 
				
			||||||
 | 
					    with pytest.raises(TypeError, match="invalid type for lines2: set"):
 | 
				
			||||||
 | 
					        lm.re_match_lines(set())  # type: ignore[arg-type]  # noqa: F821
 | 
				
			||||||
 | 
					    with pytest.raises(TypeError, match="invalid type for lines2: dict"):
 | 
				
			||||||
 | 
					        lm.re_match_lines({})  # type: ignore[arg-type]  # noqa: F821
 | 
				
			||||||
 | 
					    with pytest.raises(TypeError, match="invalid type for lines2: Source"):
 | 
				
			||||||
 | 
					        lm.fnmatch_lines(Source())  # type: ignore[arg-type]  # noqa: F821
 | 
				
			||||||
    lm.fnmatch_lines([])
 | 
					    lm.fnmatch_lines([])
 | 
				
			||||||
    lm.fnmatch_lines(())
 | 
					    lm.fnmatch_lines(())
 | 
				
			||||||
 | 
					    lm.fnmatch_lines("")
 | 
				
			||||||
    assert lm._getlines({}) == {}
 | 
					    assert lm._getlines({}) == {}  # type: ignore[arg-type,comparison-overlap]  # noqa: F821
 | 
				
			||||||
    assert lm._getlines(set()) == set()
 | 
					    assert lm._getlines(set()) == set()  # type: ignore[arg-type,comparison-overlap]  # noqa: F821
 | 
				
			||||||
 | 
					    assert lm._getlines(Source()) == []
 | 
				
			||||||
 | 
					    assert lm._getlines(Source("pass\npass")) == ["pass", "pass"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_linematcher_match_failure() -> None:
 | 
					def test_linematcher_match_failure() -> None:
 | 
				
			||||||
| 
						 | 
					@ -499,8 +508,28 @@ def test_linematcher_match_failure() -> None:
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_linematcher_consecutive():
 | 
				
			||||||
 | 
					    lm = LineMatcher(["1", "", "2"])
 | 
				
			||||||
 | 
					    with pytest.raises(pytest.fail.Exception) as excinfo:
 | 
				
			||||||
 | 
					        lm.fnmatch_lines(["1", "2"], consecutive=True)
 | 
				
			||||||
 | 
					    assert str(excinfo.value).splitlines() == [
 | 
				
			||||||
 | 
					        "exact match: '1'",
 | 
				
			||||||
 | 
					        "no consecutive match: '2'",
 | 
				
			||||||
 | 
					        "   with: ''",
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lm.re_match_lines(["1", r"\d?", "2"], consecutive=True)
 | 
				
			||||||
 | 
					    with pytest.raises(pytest.fail.Exception) as excinfo:
 | 
				
			||||||
 | 
					        lm.re_match_lines(["1", r"\d", "2"], consecutive=True)
 | 
				
			||||||
 | 
					    assert str(excinfo.value).splitlines() == [
 | 
				
			||||||
 | 
					        "exact match: '1'",
 | 
				
			||||||
 | 
					        r"no consecutive match: '\\d'",
 | 
				
			||||||
 | 
					        "    with: ''",
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("function", ["no_fnmatch_line", "no_re_match_line"])
 | 
					@pytest.mark.parametrize("function", ["no_fnmatch_line", "no_re_match_line"])
 | 
				
			||||||
def test_no_matching(function) -> None:
 | 
					def test_linematcher_no_matching(function) -> None:
 | 
				
			||||||
    if function == "no_fnmatch_line":
 | 
					    if function == "no_fnmatch_line":
 | 
				
			||||||
        good_pattern = "*.py OK*"
 | 
					        good_pattern = "*.py OK*"
 | 
				
			||||||
        bad_pattern = "*X.py OK*"
 | 
					        bad_pattern = "*X.py OK*"
 | 
				
			||||||
| 
						 | 
					@ -548,7 +577,7 @@ def test_no_matching(function) -> None:
 | 
				
			||||||
    func(bad_pattern)  # bad pattern does not match any line: passes
 | 
					    func(bad_pattern)  # bad pattern does not match any line: passes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_no_matching_after_match() -> None:
 | 
					def test_linematcher_no_matching_after_match() -> None:
 | 
				
			||||||
    lm = LineMatcher(["1", "2", "3"])
 | 
					    lm = LineMatcher(["1", "2", "3"])
 | 
				
			||||||
    lm.fnmatch_lines(["1", "3"])
 | 
					    lm.fnmatch_lines(["1", "3"])
 | 
				
			||||||
    with pytest.raises(Failed) as e:
 | 
					    with pytest.raises(Failed) as e:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue