def test_format_default(self): console = Console() output = console.format('The quick brown fox jumps over the lazy dog') self.assertEqual( repr(output), repr('The quick brown fox jumps over the lazy dog' + ' ' * 37) )
def test_write(self): stream = StringIO() console = Console(stream) console.write('The quick brown fox jumps over the lazy dog') output = stream.getvalue() self.assertEqual( repr(output), repr('The quick brown fox jumps over the lazy dog') )
def test_same_line(self): stream = StringIO() console = Console(stream) console.same_line('The quick brown fox jumps over the lazy dog') output = stream.getvalue() self.assertEqual( repr(output), repr( '\r' 'The quick brown fox jumps over the lazy dog' + ' ' * 37 ) )
def test_success(self): stream = StringIO() console = Console(stream) console.success('The quick brown fox jumps over the lazy dog') output = stream.getvalue() self.assertEqual( repr(output), repr( '\r\x1b[32m' 'The quick brown fox jumps over the lazy dog' '\x1b[39m' + ' ' * 27 + '\n' ) )
def test_format_many_options(self): console = Console() output = console.format( 'The quick brown fox jumps over the lazy dog', fg_color='RED', bg_color='YELLOW', font='BOLD', min_length=10 ) self.assertEqual( repr(output), repr( '\x1b[2m\x1b[31m\x1b[43m' 'The quick brown fox jumps over the lazy dog' '\x1b[49m\x1b[39m\x1b[0m' ) )
def test_format_fg_color(self): console = Console() output = console.format( 'The quick brown fox jumps over the lazy dog', fg_color='RED' ) self.assertEqual( repr(output), repr( '\x1b[31m' 'The quick brown fox jumps over the lazy dog' '\x1b[39m' + ' ' * 27 ) )
def __init__(self, root_url=None, error_class=None, stdout=None, stderr=None, get_input=None, **options): self.root_url = root_url or '/' self.error_class = error_class or RuntimeError self.stdout = stdout or sys.stdout self.stderr = stderr or sys.stderr self.dry_run = options['dry_run'] self.no_interactive = options['no_interactive'] self.quiet = options['quiet'] self.force = options['force'] self.git_add = options['git_add'] self.no_color = options.get('no_color') self.console = Console(self.stdout) self.get_input = get_input or default_get_input
def test_progress_bar_console_no_eta(self): stream = StringIO() console = Console(stream) progress_bar = ProgressBar(console) for i in range(1, 51): progress_bar.progress(i, 50) output = stream.getvalue() self.assertEqual( [ln.strip() for ln in output.split('\r')], [ '', '[##### ] 20.00% (10 / 50) ETA: ? |', '[######### ] 40.00% (20 / 50) ETA: ? /', '[############# ] 60.00% (30 / 50) ETA: ? -', '[################# ] 80.00% (40 / 50) ETA: ? \\', '[#####################] 100.00% (50 / 50) ETA: 0:00:00' ] )
class BaseSyncOperation(object): """Base class for website dump / load operations""" status_colors = { SyncStatus.DELETED: 'MAGENTA', SyncStatus.ADDED: 'GREEN', SyncStatus.MODIFIED: 'CYAN', } def __init__(self, root_url=None, error_class=None, stdout=None, stderr=None, get_input=None, **options): self.root_url = root_url or '/' self.error_class = error_class or RuntimeError self.stdout = stdout or sys.stdout self.stderr = stderr or sys.stderr self.dry_run = options['dry_run'] self.no_interactive = options['no_interactive'] self.quiet = options['quiet'] self.force = options['force'] self.git_add = options['git_add'] self.no_color = options.get('no_color') self.console = Console(self.stdout) self.get_input = get_input or default_get_input def status_fg_color(self, status): """Determines fg color for status""" if self.no_color: fg_color = None else: try: base_status, extra_status = status except ValueError: base_status, extra_status = status, None if extra_status == SyncStatus.SKIPPED: fg_color = None else: fg_color = self.status_colors.get(base_status, None) return fg_color def log(self, message): """Writes informative line of text to stdout""" if not self.quiet: self.console.new_line(message) def log_status(self, status, item): """Writes informative line about status of given item (in color!)""" if not self.quiet: message = '{0} {1}'.format(status, item) self.console.new_line(message, fg_color=self.status_fg_color(status)) def summary(self, summary_dict): """Writes summary line of text to stdout""" self.console.new_line('SUMMARY:') if summary_dict: for status, occurrences in summary_dict.items(): message = '\t{0} [{1}] = {2}'.format( SyncStatus.describe(status), status, occurrences) self.console.new_line(message, fg_color=self.status_fg_color(status)) else: self.console.new_line('\tNo changes!') def error(self, message): """Stops processing by raising an exception""" raise self.error_class(message) def confirm(self, *args, **kwargs): """Asks user for confirmation, providing boolean output""" if self.no_interactive: choice = True else: # Delimiter: self.console.new_line( '{s} CONFIRMATION REQUIRED: {s}'.format(s='#' * 28)) # Show diff if available: diff = kwargs.get('diff') if diff: self.console.new_line('{s} DIFF {s}'.format(s='-' * 37)) for diff_line in diff.splitlines(): if diff_line.startswith('+'): fg_color = 'GREEN' elif diff_line.startswith('-'): fg_color = 'RED' else: fg_color = None self.console.new_line(diff_line, fg_color=fg_color) self.console.new_line('{s}'.format(s='-' * 80)) # Show other messages: message = kwargs.get('message') messages = [message] if message else list(args) messages.append( kwargs.get('question', 'Do you want to apply this change?')) for message in messages: self.console.new_line(message) choice = None while choice is None: user_text = self.get_input('Y/N? ') if user_text in ('Y', 'y'): choice = True elif user_text in ('N', 'n'): choice = False # Delimiter: self.console.new_line('{s}'.format(s='#' * 80)) return choice def run(self): """Performs the operation""" raise NotImplementedError