1# Copyright 2021 The Chromium Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4"""Utilities for invoking executables. 5""" 6 7import os 8import subprocess 9import re 10 11# Regex for matching 7-bit and 8-bit C1 ANSI sequences. 12# Credit: https://stackoverflow.com/a/14693789/4692014 13_ANSI_ESCAPE_8BIT_REGEX = re.compile( 14 br""" 15 (?: # either 7-bit C1, two bytes, ESC Fe (omitting CSI) 16 \x1B 17 [@-Z\\-_] 18 | # or a single 8-bit byte Fe (omitting CSI) 19 [\x80-\x9A\x9C-\x9F] 20 | # or CSI + control codes 21 (?: # 7-bit CSI, ESC [ 22 \x1B\[ 23 | # 8-bit CSI, 9B 24 \x9B 25 ) 26 [0-?]* # Parameter bytes 27 [ -/]* # Intermediate bytes 28 [@-~] # Final byte 29 ) 30""", re.VERBOSE) 31 32 33def run_and_tee_output(args): 34 """Runs the test executable passing-thru its output to stdout (in a 35 terminal-colors-friendly way). Waits for the executable to exit. 36 37 Returns: 38 The full executable output as an UTF-8 string. 39 """ 40 output_bytes = subprocess.check_output(args) 41 # Strip ANSI / terminal escapes. 42 output_bytes = _ANSI_ESCAPE_8BIT_REGEX.sub(b'', output_bytes) 43 44 return output_bytes.decode('utf-8') 45