def __init__(self): self.print_output: bool = True self._stdout: RichConsole = RichConsole(force_terminal=True, # color_system='256', width=160) self._stderr: RichConsole = RichConsole(file=sys.stderr, force_terminal=True, # color_system='256', width=160) self._stringio: RichConsole = RichConsole(file=StringIO(), width=160)
def __init__(self, theme: dict = None): try: # pylint:disable=import-outside-toplevel from rich.console import Console as RichConsole from rich.theme import Theme if theme is None: if in_notebook(): theme = { 'repr.number': 'bold #87ff00', 'repr.attrib_name': 'bold #ff5fff', 'repr.str': 'italic #FFFF00', } with_jupyter = in_notebook() console = RichConsole(record=False, log_path=False, force_jupyter=with_jupyter, force_terminal=(not with_jupyter), log_time_format='[%X] ', theme=Theme(theme)) #, width=width) except (ImportError, ModuleNotFoundError): console = Console() self.console = console
def __init__(self): try: # pylint:disable=import-outside-toplevel from rich.console import Console as RichConsole console = RichConsole(log_path=False, width=TERM_WIDTH) except (ImportError, ModuleNotFoundError): console = Console() self.console = console
def getResourceTreeText(self, maxLevel:int=0) -> str: """ This function will generate a Text tree of a CSE's resource structure. """ from rich.console import Console as RichConsole console = RichConsole(color_system=None) console.begin_capture() console.print(self.getResourceTreeRich()) return '\n'.join([item.rstrip() for item in console.end_capture().splitlines()])
def __init__( self, level=logging.DEBUG, console=RichConsole(), ): super().__init__(level=level) self.console = console self._render = LogRender(show_level=True)
def test_prompt_disallows_empty_response(mocker): console = RichConsole(file=io.StringIO()) Prompt.prompt_( "What is your name?", console=console, stream=io.StringIO("\nfoo"), ) expected = ("What is your name?: Response required. Please try again.\n" "What is your name?: ") assert console.file.getvalue() == expected
def test_prompt_confirm(default, inner): console = RichConsole(file=io.StringIO()) assert (Confirm.ask( "exit?", console=console, stream=io.StringIO("y\n"), default=default, ) is True) output = console.file.getvalue() assert output == f"exit? [{inner}]: "
def test_prompt_default(mocker): console = RichConsole(file=io.StringIO()) mocked_validator = mocker.MagicMock(return_value="default") assert (Prompt.ask( "What is your name?", console=console, stream=io.StringIO(""), default="default", validator=mocked_validator, ) == "default") assert console.file.getvalue() == "What is your name? [default]: " mocked_validator.assert_has_calls([call("default")])
def table(state): table = RichTable(title="Results") data = state.get("output", []) if len(data) > 0: for column in data[0].keys(): table.add_column(column) for item in data: table.add_row(*item.values()) RichConsole().print(table)
def fake_shell(state): console = RichConsole() for result in state.get("output", []): server, host, command, output = ( result["server"], result["host"], result["command"], result["output"], ) console.print(f"ubuntu@{host}|{server} $ {command}") console.print(output) console.print()
def test_prompt_interrupt_message_not_interleaved(prompt_cls, side_effect, mocker): """Test that the interrupt message is not interleaved with the prompt.""" prompt = "should print exception in the next line" console = RichConsole(file=io.StringIO()) with pytest.raises(side_effect): mocker.patch.object(console, "input", side_effect=side_effect) prompt_cls.ask(prompt=prompt, console=console) # as we are raising side_effect on the input, unfortunately we cannot # assert for the prompt string, only the newline. assert console.file.getvalue() == "\n"
def test_prompt_with_conditional_skip(mocker, default, brack): console = RichConsole(file=io.StringIO()) mocked_validator = mocker.MagicMock(return_value="something") assert (Prompt.prompt_( "What is your name?", console=console, allow_omission=True, stream=io.StringIO("n\n"), default=default, validator=mocked_validator, ) is None) assert console.file.getvalue() == f"What is your name? {brack}: " mocked_validator.assert_not_called()
def test_prompt_shows_message_from_validator_response(mocker): console = RichConsole(file=io.StringIO()) mocked_validator = mocker.MagicMock( return_value=("foo@email", "failed to send a verification email")) assert (Prompt.ask( "what is your email?", console=console, stream=io.StringIO("foo@email"), validator=mocked_validator, ) == "foo@email") mocked_validator.assert_has_calls([call("foo@email")]) expected = "what is your email?: failed to send a verification email\n" assert console.file.getvalue() == expected
def test_prompt_retries_on_invalid_response_from_validator(mocker): console = RichConsole(file=io.StringIO()) mocked_validator = mocker.MagicMock( side_effect=[InvalidResponse("it is a number"), "foo"]) assert (Prompt.ask( "what is your name?", console=console, stream=io.StringIO("3\nfoo"), validator=mocked_validator, ) == "foo") mocked_validator.assert_has_calls([call("3"), call("foo")]) expected = "what is your name?: it is a number\nwhat is your name?: " assert console.file.getvalue() == expected
def main(name, tag, region, sort, json): # Search search = {f'tag:{k}': v for k, v in dict(tag).items()} if name: search['tag:Name'] = name servers = find_instances(search, contains=True, region=region) # JSON mode if json: print(pyjson.dumps(servers, indent=2)) sys.exit(0) # Table mode table = RichTable(title=f'Instances ({region})') fields = ['Name', 'PrivateIp', 'PublicIp', 'InstanceId'] for header in fields: table.add_column(header) for server in sorted(servers, key=lambda k: k[sort]): table.add_row(*[server.get(f) for f in fields]) RichConsole().print(table)
def __init__(self, trees, raw_data_width=16): self.trees = trees self.raw_data_width = raw_data_width self.console = RichConsole(theme=default_theme)
def __init__(self): self.rich = RichConsole() self.debug_enabled = False
def test_prompt_str(): console = RichConsole(file=io.StringIO()) assert (Prompt.ask("What is your name?", console=console, stream=io.StringIO("foo")) == "foo") assert console.file.getvalue() == "What is your name?: "
class Console(Table): _verbose = False console = RichConsole() logger = logger level = logging.DEBUG def __init__(self, name=None, log=False): super().__init__( box=None if name is None else box.SQUARE, show_header=name is not None, expand=True) if name is None: self.add_row(" ") self.thread = Operation(self) def debug(self, message, silent=False): self.logger.debug(message) if not silent: self._annotate(message, style="dim") def info(self, message): self.logger.info(message) if not self._verbose: self._annotate(message, "dim") def notice(self, message, silent=False): if self.logger.isEnabledFor(25): self.logger._log(25, message, args=None) if not silent: self._annotate(message, style="dim") def warn(self, message): self.logger.warn(message) if not self._verbose: self._annotate(message, "dark_red") def error(self, message): self.logger.error(message) if not self._verbose: self._annotate(message, "bold red") def critical(self, message): if isinstance(message, str): self.logger.critical(message) if not self._verbose: self._annotate(message, "bold red") else: self.stop() try: self.console.print_exception() except ValueError: self.console.print(message.__repr__()) os._exit(1) def item(self, message): self.notice(message, silent=True) if self._verbose: return self service = self.__class__(name=message) service.add_column(message, justify="center") service.thread = self.thread.live self.add_row(service) self.spacer() return service def spacer(self): self.add_row() def task(self, message, function=None, args=[], done=None): self.notice(message, silent=True) (text, progress, busy) = self._add(message) results = function(*args) if done.__class__.__name__ == 'function': done = done(results) if done is not None: text._text = [done] self.notice(done, silent=True) busy._text = [""] progress.pulse = False progress.update(completed=progress.total) self._annotate() return results def tasklist(self, message, iterables=[], wait=None, done=None): if '__len__' in dir(iterables) and not len(iterables) > 0: return self.notice(message, silent=True) (text, progress, busy) = self._add(message, iterables=iterables) if wait is not None: self.debug(wait) else: self._annotate() for completed, iterable in enumerate(iterables, 1): if wait is not None: self._annotate() yield iterable if wait is not None: self.debug(wait) progress.update(completed=completed) if done is not None: self.notice(done, silent=True) text._text = [done] busy._text = [""] progress.pulse = False progress.update(completed=progress.total) self._annotate() def list(self, dictionaries=[]): if not isinstance(dictionaries, list): dictionaries = [dictionaries] if not len(dictionaries) > 0: return t = Table.grid(expand=True) for k in dictionaries[0].keys(): t.add_column(str(k)) for d in dictionaries: t.add_row(*d.values()) if self._verbose: self.console.print(t) else: self.add_row(t) def input(self, message): def readchar(): fd = sys.stdin.fileno() settings = termios.tcgetattr(fd) try: tty.setraw(sys.stdin.fileno()) char = sys.stdin.read(1) finally: termios.tcsetattr(fd, termios.TCSADRAIN, settings) if char == '\x03': raise KeyboardInterrupt elif char == '\x04': raise EOFError return char def read(main, message, value): (text, value, _) = self._add(message, override=value) text.style = "b" value.style = "i" try: self.refresh() char = None while True: with console.thread.live._lock: char = readchar() # Enter if ord(char) == 13: break # Delete elif ord(char) in [27]: continue # Backspace elif ord(char) == 127: value._text = [''.join(value._text)[:-1]] else: value._text = [''.join([*value._text, char])] self.refresh() except (KeyboardInterrupt, EOFError): value.style = None self.stop() os._exit(0) if not self._verbose: value = Text("") input_thread = threading.Thread(target=read, args=(self, message, value)) input_thread.start() input_thread.join() return ''.join(value._text) else: sys.stdout.write(message) sys.stdout.flush() return input() def verbose(self): if self._verbose: return log = Log(console=self.console, level=self.level) self.stop() self.logger.addHandler(log) self._verbose = True def _add(self, message, iterables=[], override=None): key = Text(message, overflow='ellipsis', no_wrap=True) busy = Text() if override is None: total = 1.0 pulse = True try: total = len(iterables) if iterables != [] else 1 pulse = iterables == [] # Not all iterables have a length except TypeError: pass busy._text = ["→"] color = Style(color="rgb(161, 209, 255)", dim=True) value = ProgressBar(total=total, pulse=pulse, complete_style=color, finished_style=color, pulse_style=color) else: value = override operation = Table(box=None, show_header=False, show_footer=False, show_edge=True, padding=(0, 0 if self.show_header else 1)) operation.add_column(width=3 if self.show_header else 2, justify="center") operation.add_column(width=62 if self.show_header else 60) operation.add_column() operation.add_row(busy, key, value) self.add_row(operation) return (key, value, busy) def _annotate(self, message="", style=None): if self._verbose: return self.caption = message self.caption_style = style self.refresh() def start(self): if not console.thread.live._started: self.thread.start() def refresh(self): if self.thread is not None: self.thread.refresh() def stop(self): if console.thread.live._started: self.thread.stop() self.console.print()
""" Import the necessary ``Rich`` objects, and then import this module as needed elsewhere. """ from rich.style import Style as RichStyle from rich.console import Console as RichConsole from rich.progress import Progress as RichProgress from rich.syntax import Syntax as RichSyntax _console = RichConsole()