Skip to content

Commit 7771bff

Browse files
committed
feat: support return_what_before_match in expect functions
1 parent c50777c commit 7771bff

File tree

3 files changed

+77
-1
lines changed

3 files changed

+77
-1
lines changed

docs/usages/expecting.rst

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ All of these functions share these possible keyword arguments:
2020

2121
Will raise an exception if the pattern is found in the output, if specified. (Default: None)
2222

23+
- ``return_what_before_match``
24+
25+
Will return the bytes read before the match if specified. (Default: False)
26+
2327
*****************************************
2428
:func:`~pytest_embedded.dut.Dut.expect`
2529
*****************************************
@@ -130,6 +134,40 @@ What's more, argument ``pattern`` could be a list of all supported types.
130134
131135
If you set ``expect_all`` to ``True``, the :func:`~pytest_embedded.dut.Dut.expect` function would return with a list of returned values of each item.
132136

137+
You can also set ``return_what_before_match`` to ``True`` to get the bytes read before the match, instead of the match object.
138+
139+
.. code:: python
140+
141+
import pexpect
142+
143+
def test_expect_before_match(dut):
144+
dut.write('this would be redirected')
145+
146+
res = dut.expect('would', return_what_before_match=True)
147+
assert res == b'this '
148+
149+
res = dut.expect_exact('be ', return_what_before_match=True)
150+
assert res == b' '
151+
152+
res = dut.expect('ected', return_what_before_match=True)
153+
assert res == b'redir'
154+
155+
.. hint::
156+
157+
For better performance when retrieving text before a pattern, use:
158+
159+
.. code:: python
160+
161+
before_str = dut.expect('pattern', return_what_before_match=True).decode('utf-8')
162+
163+
Instead of:
164+
165+
.. code:: python
166+
167+
before_str = dut.expect('(.+)pattern').group(1).decode('utf-8')
168+
169+
The latter performs unnecessary recursive matching of preceding bytes.
170+
133171
***********************************************
134172
:func:`~pytest_embedded.dut.Dut.expect_exact`
135173
***********************************************

pytest-embedded/pytest_embedded/dut.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,17 @@ def write(self, s: AnyStr) -> None:
6767
def _pexpect_func(func) -> Callable[..., Union[Match, AnyStr]]:
6868
@functools.wraps(func)
6969
def wrapper(
70-
self, pattern, *args, expect_all: bool = False, not_matching: List[Union[str, re.Pattern]] = (), **kwargs
70+
self,
71+
pattern,
72+
*args,
73+
expect_all: bool = False,
74+
not_matching: List[Union[str, re.Pattern]] = (),
75+
return_what_before_match: bool = False,
76+
**kwargs,
7177
) -> Union[Union[Match, AnyStr], List[Union[Match, AnyStr]]]:
78+
if return_what_before_match and expect_all:
79+
raise ValueError('`return_what_before_match` and `expect_all` cannot be `True` at the same time.')
80+
7281
patterns = to_list(pattern)
7382
res = []
7483
while patterns:
@@ -101,6 +110,9 @@ def wrapper(
101110
else:
102111
break # one succeeded. leave the loop
103112

113+
if return_what_before_match:
114+
return self.pexpect_proc.before
115+
104116
if len(res) == 1:
105117
return res[0]
106118

@@ -121,6 +133,8 @@ def expect(self, pattern, **kwargs) -> Match:
121133
expect_all (bool): need to match all specified patterns if this flag is `True`.
122134
Otherwise match any of them could pass
123135
not_matching: string, or compiled regex, or a list of string and compiled regex.
136+
return_what_before_match (bool): return the bytes before the matched pattern.
137+
Cannot be specified together with `expect_all`
124138
125139
Returns:
126140
`AnyStr` or `re.Match`
@@ -143,6 +157,8 @@ def expect_exact(self, pattern, **kwargs) -> Match:
143157
expect_all (bool): need to match all specified patterns if this flag is `True`.
144158
Otherwise match any of them could pass
145159
not_matching: string, or compiled regex, or a list of string and compiled regex.
160+
return_what_before_match (bool): return the bytes before the matched pattern.
161+
Cannot be specified together with `expect_all`
146162
147163
Returns:
148164
`AnyStr` or `re.Match`

pytest-embedded/tests/test_base.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,28 @@ def test_expect_unity_test_output_multi_dut_with_illegal_chars(dut):
496496
assert junit_report[1].find('failure') is not None
497497

498498

499+
def test_expect_before_match(testdir):
500+
testdir.makepyfile(r"""
501+
import pexpect
502+
503+
def test_expect_before_match(dut):
504+
dut.write('this would be redirected')
505+
506+
res = dut.expect('would', return_what_before_match=True)
507+
assert res == b'this '
508+
509+
res = dut.expect_exact('be ', return_what_before_match=True)
510+
assert res == b' '
511+
512+
res = dut.expect('ected', return_what_before_match=True)
513+
assert res == b'redir'
514+
""")
515+
516+
result = testdir.runpytest()
517+
518+
result.assert_outcomes(passed=1)
519+
520+
499521
def test_duplicate_stdout_popen(testdir):
500522
testdir.makepyfile(r"""
501523
import pytest

0 commit comments

Comments
 (0)