Skip to content

Commit d57261b

Browse files
committed
feat: handle better unhandled escape seq
Move the unhandled escape sequence check sooner to exec even if the test fails by timeout (which it is likely if the output contains escape sequences that makes the prompt or type regexps to fail and not match). Add also a little of stats for introspection.
1 parent f6c1baf commit d57261b

1 file changed

Lines changed: 45 additions & 23 deletions

File tree

byexample/runner.py

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import unicode_literals
22
import pexpect, pexpect.popen_spawn, time, operator, os, itertools, contextlib
3+
4+
import pprint
35
import signal
46
import subprocess
57
from . import regex as re
@@ -197,6 +199,9 @@ def were_unhandled_escape_sequences(self):
197199
def reset_unhandled_state(self):
198200
self._were_unhandled_escape_sequences = False
199201

202+
def stats(self):
203+
return self._screen.stats()
204+
200205

201206
class PopenSpawnExt(ReadFilter, pexpect.popen_spawn.PopenSpawn):
202207
''' This is a compatibility layer that extends pexpect's PopenSpawn
@@ -584,29 +589,54 @@ def _exec_and_wait(self, source, options, *, from_example=None, **kargs):
584589
with log_with("sendlines") as clog2:
585590
clog2.debug("\n > " + '\n > '.join(lines))
586591

587-
self._last_num_lines_sent = 0
588-
for line in lines[:-1]:
592+
try:
593+
self._last_num_lines_sent = 0
594+
for line in lines[:-1]:
595+
with profile_ctx("sendline"):
596+
# turn the echo off (may be)
597+
self._may_turn_echo_off(options)
598+
599+
self._sendline(line)
600+
self._last_num_lines_sent += 1
601+
self._expect_prompt_or_type(
602+
options, countdown, input_list=input_list
603+
)
604+
589605
with profile_ctx("sendline"):
590606
# turn the echo off (may be)
591607
self._may_turn_echo_off(options)
592608

593-
self._sendline(line)
609+
self._sendline(lines[-1])
594610
self._last_num_lines_sent += 1
611+
595612
self._expect_prompt_or_type(
596-
options, countdown, input_list=input_list
613+
options,
614+
countdown,
615+
prompt_re=self._PS1_re,
616+
input_list=input_list
597617
)
618+
self._expect_delayed_output(options)
619+
finally:
620+
unh = self._interpreter.were_unhandled_escape_sequences()
621+
622+
if from_example is not None and unh:
623+
from_example.add_note_on_failure(
624+
"Escape/control sequences were detected. If the output looks\n" +\
625+
"scrambled or dirty, you may try a full terminal emulation with '+term=ansi'" +\
626+
("\nRun byexample with -v to get more debugging details" if not clog().isEnabledFor(INFO) else "")
627+
)
628+
629+
if clog().isEnabledFor(INFO):
630+
from_example.add_note_on_failure(
631+
"Unhandled sequences: " + pprint.pformat(
632+
list(
633+
self._interpreter._screen.
634+
_unhandled_escape_seq_cnt.keys()
635+
)
636+
)
637+
)
598638

599-
with profile_ctx("sendline"):
600-
# turn the echo off (may be)
601-
self._may_turn_echo_off(options)
602-
603-
self._sendline(lines[-1])
604-
self._last_num_lines_sent += 1
605-
606-
self._expect_prompt_or_type(
607-
options, countdown, prompt_re=self._PS1_re, input_list=input_list
608-
)
609-
self._expect_delayed_output(options)
639+
self._interpreter.reset_unhandled_state()
610640

611641
if input_list:
612642
s = short_string(input_list[0][-1])
@@ -623,14 +653,6 @@ def _exec_and_wait(self, source, options, *, from_example=None, **kargs):
623653
with log_with("raw-got") as clog2:
624654
clog2.debug("\n" + ''.join(self._output_between_prompts))
625655

626-
unh = self._interpreter.were_unhandled_escape_sequences()
627-
self._interpreter.reset_unhandled_state()
628-
629-
if from_example is not None and unh:
630-
from_example.add_note_on_failure(
631-
"Escape/control sequences were detected. If the output looks\n" +\
632-
"scrambled or dirty, you may try a full terminal emulation with '+term=ansi'"
633-
)
634656
out = self._get_output(options)
635657
return out
636658

0 commit comments

Comments
 (0)