def dealSignal(*argv): for index in range(cur_index + 1, len(res['news'])): qs_default_console.print(Padding(res['news'][index], (0, int(0.2 * qs_default_console.width)))) qs_default_console.print() qs_default_console.print('-' * qs_default_console.width) qs_default_console.print(res['weiyu'] + '\n', justify='center') if '--save' in sys.argv: import os from .NetTools.NormalDL import normal_dl st.stop() name = normal_dl(res['image'], set_name='news.png') st.start() if system == 'darwin': qs_default_console.print('Preview' if user_lang != 'zh' else '预览', justify='center') from .ImageTools.ImagePreview import image_preview st.update(status='loading image..' if user_lang != 'zh' else '加载图片中..') image_preview(open(name), qs_console_status=st) exit(0)
def test_rich_console(): renderable = "test renderable" style = Style(color="red") options = ConsoleOptions( ConsoleDimensions(80, 25), legacy_windows=False, min_width=10, max_width=20, is_terminal=False, encoding="utf-8", ) expected_outputs = [ Segment(renderable, style=style), Segment(" " * (20 - len(renderable)), style=style), Segment("\n", style=None), ] padding_generator = Padding(renderable, style=style).__rich_console__( Console(), options) for output, expected in zip(padding_generator, expected_outputs): assert output == expected
def __rich_console__(self, c: Console, co: ConsoleOptions) -> RenderResult: test_results = sorted( self.all_tests_in_session, key=lambda r: r.test.timer.duration, reverse=True ) grid = Table.grid(padding=(0, 2, 0, 0)) grid.add_column(justify="right") # Time taken grid.add_column() # Test ID grid.add_column() # Test description for result in test_results[: self.num_tests_to_show]: time_taken_secs = result.test.timer.duration time_taken_millis = time_taken_secs * 1000 test_id = format_test_id(result) description = result.test.description grid.add_row( f"[b]{time_taken_millis:.0f}[/b]ms", Text(test_id, style="muted"), description, ) num_slowest_displayed = min( len(self.all_tests_in_session), self.num_tests_to_show ) panel = Panel( RenderGroup( Padding( f"Median: [b]{self._median_secs * 1000:.2f}[/b]ms" f" [muted]|[/muted] " f"99th Percentile: [b]{self._percentile99_secs * 1000:.2f}[/b]ms", pad=(0, 0, 1, 0), ), grid, ), title=f"[b white]{num_slowest_displayed} Slowest Tests[/b white]", style="none", border_style="rule.line", ) yield panel
def commits( id: str, workspace: str = get_workspace(), slug: str = get_slug(), ): """View commits of PR by ID""" url = commits_url.format(workspace=workspace, slug=slug, id=id) console = Console() with console.status("[bold green]Loading..."): resp = get(url) handle_error(resp) for commit in resp["values"]: hash = commit["hash"] author = commit["author"]["raw"] date = commit["date"] message = commit["message"] console.print(f"[bold]commit {hash}[/bold]") console.print(f"[cyan]Author: {author}") console.print(f"[cyan]Date: {date}") console.print(Padding(message.strip(), (1, 4)))
def updateSuper(self, details): table = Table(box=box.SIMPLE) table.add_column("Map") table.add_column("Requirement") for row in range(self.height): output = "" for col in range(self.width): if self.map[row][col] == 1: output += "#" elif self.map[row][col] == 0: output += " " if row < len(details): for i in range(0, len(details)): if (row == i): table.add_row(output, details[i]) else: table.add_row(output, "") table.add_row(Padding("\n", 1)) return Align.center(table)
def messages(cli_args): r = requests.get( "https://passio3.com/www/goServices.php?getAlertMessages=1&json=%7B%22systemSelected0%22%3A%2276%22%2C%22amount%22%3A1%2C%22routesAmount%22%3A0%7D" ) messages_data = r.json() messages_data = messages_data["msgs"] messages_data_new = [{ "title": m["name"], "html": m["html"], "date_from": m["from"], "date_to": m["to"] } for m in messages_data] console = Console() console.print(Panel(Text("Messages", justify="center", style="bold"))) for m in messages_data_new: group = RenderGroup( Text(m["title"], justify="center", style="bold"), Text(m["date_from"] + " to " + m["date_to"], justify="center"), Padding(Text(m["html"]), (1, 0, 0, 0))) console.print(Panel(group, expand=True))
def output_why_test_failed(self, test_result: TestResult): err = test_result.error if isinstance(err, TestFailure): src_lines, line_num = inspect.getsourcelines(test_result.test.fn) if err.operator in Comparison: src = "".join(src_lines) src = Syntax( src, "python", start_line=line_num, line_numbers=True, highlight_lines={err.error_line}, background_color="default", theme="ansi_dark", ) src = Padding(src, (1, 0, 1, 4)) console.print(src) if err.operator == Comparison.Equals: self.print_failure_equals(err) else: self.print_traceback(err)
def get_table_renderable(title, cols, rows): """ Returns a Rich Table constructed from supplied cols and rows """ # Initialize Rich Table as renderable renderable = Table(title=title) # Add number column renderable.add_column("#") # Add columns [renderable.add_column(col) for col in cols] # Iterate over rows for i, row in enumerate(rows): # Add row renderable.add_row(str(i), *[str(r) if r else "" for r in row]) # Pad the renderable renderable = Padding(renderable, (1, 1)) # Return renderable return renderable
def output_test_failed_location(self, test_result: TestResult): assert_msg = Text("") if isinstance(test_result.error, TestAssertionFailure): if test_result.error.assert_msg: assert_msg = Text.assemble((" - ", "dim"), test_result.error.assert_msg) else: assert_msg = Text("") output_str = ( f"Failed at {os.path.relpath(test_result.test.path, Path.cwd())}:" f"{test_result.error.error_line}") else: # This is what we'd expect to see if the test failed for something like # an error during fixture resolution. output_str = ( f"Failed at {os.path.relpath(test_result.test.path, Path.cwd())}" ) output_text = Text.assemble(output_str, assert_msg) self.console.print(Padding( output_text, pad=(1, 0, 0, 2), ))
def table(info): table = Table.grid(expand=False) table.add_column("Hardware", justify="left", style="cyan") table.add_column("product", justify="right", style="magenta") table.add_column("Status", justify="left", style="green") table.add_column("Num", justify="right", style="magenta", width=3) for i, cpu in enumerate(info['cpus']): usage = str(cpu.get('usage', '0')) + '%' table.add_row("CPU", Padding(cpu.get('name', ''), (0, 1)), usage, str(i)) for i, gpu in enumerate(info['gpus']): usage = str(gpu.get('usage', '0')) + '%' memory = str(gpu.get('men_used', '0')) + '/' + str( gpu.get('men_total', '0')) temp = str(gpu.get('temp', '0')) + '°' table.add_row("GPU", Padding(gpu.get('name', ''), (0, 1)), usage, str(i)) table.add_row("GPU", "", memory, str(i)) table.add_row("GPU", "", temp, str(i)) for i, disk in enumerate(info['disk']): usage = int(disk.get('used', 0) / disk.get('total', 1) * 100) usage = str(usage) + '%' table.add_row("DISK", Padding("disk " + str(i), (0, 1)), usage, "") ram_usage = int(info['mem'].get('used', 0) / info['mem'].get('total', 1) * 100) ram_usage = str(ram_usage) + '%' table.add_row("RAM", Padding("ram", (0, 1)), ram_usage, "") table.add_row("NET", Padding("received", (0, 1)), str(info['net'].get('in', '0')) + "MB", "") table.add_row("NET", Padding("sent", (0, 1)), str(info['net'].get('out', '0')) + "MB", "") return Panel( Align.center(table), box=box.ROUNDED, border_style="bright_blue", )
def create_summary_panel( counts: dict[Enum, int], outcome_enum: type[CollectionOutcome] | type[TaskOutcome], description_total: str, ) -> Panel: """Create a summary panel.""" n_total = sum(counts.values()) grid = Table.grid("", "", "") grid.add_row( Padding(str(n_total), pad=_HORIZONTAL_PADDING), Padding(description_total, pad=_HORIZONTAL_PADDING), Padding("", pad=_HORIZONTAL_PADDING), style="#ffffff", ) for outcome, value in counts.items(): if value: percentage = f"({100 * value / n_total:.1f}%)" grid.add_row( Padding(str(value), pad=_HORIZONTAL_PADDING), Padding( outcome.description, # type: ignore[attr-defined] pad=_HORIZONTAL_PADDING, ), Padding( percentage, pad=_HORIZONTAL_PADDING, ), style=outcome.style_textonly, # type: ignore[attr-defined] ) panel = Panel( grid, title="[bold #ffffff]Summary[/bold #ffffff]", expand=False, style="none", border_style=outcome_enum.FAIL.style if counts[outcome_enum.FAIL] else outcome_enum.SUCCESS.style, ) return panel
def get_list_renderable( self, interactive=False, limit=None, offset=0, sort_by=None, filter_by=None, highlight_id=None, ): """ Returns a Rich table renderable for the interface list view """ # Define max limit limit_max = 1000 # Initialize limie limit = limit or limit_max # Get limit where max is 1000 limit = min(limit, limit_max) # Get display map display_map = self.list_display_map # Get items items = self.db_session.query(self.Item) # Check if filter by is not null if filter_by: # Apply filters items = self.filter(queryset=items, display_map=display_map, tuples=filter_by) # Check if sort by is not null if sort_by: # Apply sort fields items = self.sort(*sort_by, queryset=items, display_map=display_map) # Get row count row_count = items.count() # Get page count page_count = math.ceil(row_count / limit) # Define title title = (f"{self.name}: {self.db_table_name}\n" f"Page {int(offset / limit) + 1} of {page_count} " f"({row_count} {self.inflector.plural('row', row_count)})") # Limit items items = items.offset(offset).limit(limit) # Initialize Rich Table as renderable renderable = Table(title=title) # Get display fields display_fields = self.display_list_by # Initialize fields fields = [] # Iterate over display fields for field, display in display_fields.items(): # Create column renderable.add_column(display) # Add field to fields fields.append(field) # Iterate over items for item in items: # Initialize style style = "" # Get item ID item_id = item.id # Check if item is highlighted if item_id == highlight_id: # Set style style = "white on blue" # Add row renderable.add_row( *[str(getattr(item, field)) for field in fields], style=style) # Check if interactive if interactive: # Initialize caption caption = "c\[ommands]: Show available commands" # noqa # Initialize sub-caption sub_caption = "" # Check if sort by is not null if sort_by: # Add sort sub-caption sub_caption += f"sort {(' ' + OPERATOR_AND + ' ').join(sort_by)}\n" # Check if filter by is not null if filter_by: # Get filter strings filter_strings = [f"{f} = {v}" for f, v in filter_by] # Add filter sub-caption sub_caption += ( f"filter {(' ' + OPERATOR_AND + ' ').join(filter_strings)}\n" ) # Check if sub-caption if sub_caption: # Combine caption and sub-caption caption = sub_caption + "\n" + caption # Set caption renderable.caption = caption.strip("\n") # Pad renderable renderable = Padding(renderable, (1, 1)) # Return renderable and row count return renderable, row_count
for x in y ], expand=True, column_first=True, ), title=name, ) for name, y in mail.items() ], column_first=True, ) # Partition the screen into manageable chunks layout = Layout() layout.split_column( Layout(Padding(""), name="padding", size=1), Layout(Rule(platform.node()), name="title", size=1), Layout(name="content"), ) timed_layout = Layout() timed_layout.split_row( Layout(Panel(events, title="Calendar"), name="calendar"), Layout(Panel(mails, title="Emails"), name="email"), ) layout["content"].split_row( Layout(Panel(fetch), name="fetch"), Layout(Panel(timed_layout, title=str(datetime.date.today())), name="timed", ratio=4), ) # Do it console.print(layout)
status, message = splash_status() if status: console.print(f'[green]{message}[/green]') else: console.print('Splash is [bold red]down[/bold red]: ', message) m = Monitoring() backend_up = m.backend_status if not backend_up: console.print('[bold red]Backend not up, breaking.[/bold red]') sys.exit() console.print('Services currently running:') running = AbstractManager.is_running() for service, number in running: s = Padding(f'{service} ({int(number)} service(s))', (0, 2)) console.print(s) console.print('Current queues:') for q, priority in m.queues: s = Padding(f'{q} Recently enqueued captures: {int(priority)}', (0, 2)) console.print(s) # ------------------ console.print('Captures details:') captures = m.ongoing_captures console.print(f'Queue length: [yellow]{len(captures)}[/yellow]') for uuid, rank, d in captures: a = Padding(f'{uuid} Rank: {int(rank)}', (0, 2)) console.print(a) console.print(d)
def update(self): self.live.update( Layout(Padding(Markdown(self.slides[self.index]), (2, 2))))
def run(sparv_datadir: Optional[str] = None): """Query user about data dir path unless provided by argument, and populate path with files.""" default_dir = pathlib.Path(appdirs.user_data_dir("sparv")) current_dir = paths.get_data_path() path: pathlib.Path using_env = bool(os.environ.get(paths.data_dir_env)) if sparv_datadir: # Specifying a path on the command line will perform the setup using that path, even if the environment # variable is set using_env = False path = pathlib.Path(sparv_datadir) else: console.print( "\n[b]Sparv Data Directory Setup[/b]\n\n" f"Current data directory: [green]{current_dir or '<not set>'}[/green]\n\n" "Sparv needs a place to store its configuration files, language models and other data. " "After selecting the directory you want to use for this purpose, Sparv will populate it with a default " "config file and presets. Any existing files in the target directory will be backed up. Any previous " "backups will be overwritten.") console.print( Padding( "[b]Tip:[/b] This process can also be completed non-interactively. Run 'sparv setup --help' for details. " f"You may also override the data directory setting using the environment variable '{paths.data_dir_env}'.", (1, 4))) if using_env: try: cont = Confirm.ask( f"[b red]NOTE:[/b red] Sparv's data directory is currently set to '{current_dir}' using the " f"environment variable '{paths.data_dir_env}'. This variable takes precedence over any previous " f"path set using this setup process. To change the path, either edit the environment variable, or " f"delete the variable and rerun the setup command.\n" "Do you want to continue the setup process using the above path?" ) except KeyboardInterrupt: console.print("\nSetup interrupted.") sys.exit() if not cont: console.print("\nSetup aborted.") sys.exit() path = current_dir else: # Ask user for path if current_dir: msg = f" Leave empty to continue using '{current_dir}':" else: msg = f" Leave empty to use the default which is '{default_dir}':" try: console.print( f"Enter the path to the directory you want to use.{msg}") path_str = input().strip() except KeyboardInterrupt: console.print("\nSetup interrupted.") sys.exit() if path_str: path = pathlib.Path(path_str) else: if current_dir: path = current_dir else: path = default_dir try: # Expand any "~" path = path.expanduser() # Create directories dirs = [ paths.bin_dir.name, paths.config_dir.name, paths.models_dir.name ] path.mkdir(parents=True, exist_ok=True) for d in dirs: (path / d).mkdir(exist_ok=True) except: console.print( "\nAn error occurred while trying to create the directories. " "Make sure the path you entered is correct, and that you have the necessary read/write permissions." ) sys.exit(1) if not using_env: # Save data dir setting to config file config_dict = {"sparv_data": str(path)} paths.sparv_config_file.parent.mkdir(parents=True, exist_ok=True) with open(paths.sparv_config_file, "w") as f: yaml.dump(config_dict, f) copy_resource_files(path) # Save Sparv version number to a file in data dir (path / VERSION_FILE).write_text(__version__) console.print( f"\nSetup completed. The Sparv data directory is set to '{path}'.")
def rich_format_help( *, obj: Union[click.Command, click.Group], ctx: click.Context, markup_mode: MarkupMode, ) -> None: """Print nicely formatted help text using rich. Based on original code from rich-cli, by @willmcgugan. https://github.com/Textualize/rich-cli/blob/8a2767c7a340715fc6fbf4930ace717b9b2fc5e5/src/rich_cli/__main__.py#L162-L236 Replacement for the click function format_help(). Takes a command or group and builds the help text output. """ console = _get_rich_console() # Print usage console.print(Padding(highlighter(obj.get_usage(ctx)), 1), style=STYLE_USAGE_COMMAND) # Print command / group help if we have some if obj.help: # Print with some padding console.print( Padding( Align( _get_help_text( obj=obj, markup_mode=markup_mode, ), pad=False, ), (0, 1, 1, 1), )) panel_to_arguments: DefaultDict[str, List[click.Argument]] = defaultdict(list) panel_to_options: DefaultDict[str, List[click.Option]] = defaultdict(list) for param in obj.get_params(ctx): # Skip if option is hidden if getattr(param, "hidden", False): continue if isinstance(param, click.Argument): panel_name = (getattr(param, _RICH_HELP_PANEL_NAME, None) or ARGUMENTS_PANEL_TITLE) panel_to_arguments[panel_name].append(param) elif isinstance(param, click.Option): panel_name = (getattr(param, _RICH_HELP_PANEL_NAME, None) or OPTIONS_PANEL_TITLE) panel_to_options[panel_name].append(param) default_arguments = panel_to_arguments.get(ARGUMENTS_PANEL_TITLE, []) _print_options_panel( name=ARGUMENTS_PANEL_TITLE, params=default_arguments, ctx=ctx, markup_mode=markup_mode, console=console, ) for panel_name, arguments in panel_to_arguments.items(): if panel_name == ARGUMENTS_PANEL_TITLE: # Already printed above continue _print_options_panel( name=panel_name, params=arguments, ctx=ctx, markup_mode=markup_mode, console=console, ) default_options = panel_to_options.get(OPTIONS_PANEL_TITLE, []) _print_options_panel( name=OPTIONS_PANEL_TITLE, params=default_options, ctx=ctx, markup_mode=markup_mode, console=console, ) for panel_name, options in panel_to_options.items(): if panel_name == OPTIONS_PANEL_TITLE: # Already printed above continue _print_options_panel( name=panel_name, params=options, ctx=ctx, markup_mode=markup_mode, console=console, ) if isinstance(obj, click.MultiCommand): panel_to_commands: DefaultDict[str, List[click.Command]] = defaultdict(list) for command_name in obj.list_commands(ctx): command = obj.get_command(ctx, command_name) if command and not command.hidden: panel_name = (getattr(command, _RICH_HELP_PANEL_NAME, None) or COMMANDS_PANEL_TITLE) panel_to_commands[panel_name].append(command) # Print each command group panel default_commands = panel_to_commands.get(COMMANDS_PANEL_TITLE, []) _print_commands_panel( name=COMMANDS_PANEL_TITLE, commands=default_commands, markup_mode=markup_mode, console=console, ) for panel_name, commands in panel_to_commands.items(): if panel_name == COMMANDS_PANEL_TITLE: # Already printed above continue _print_commands_panel( name=panel_name, commands=commands, markup_mode=markup_mode, console=console, ) # Epilogue if we have it if obj.epilog: # Remove single linebreaks, replace double with single lines = obj.epilog.split("\n\n") epilogue = "\n".join([x.replace("\n", " ").strip() for x in lines]) epilogue_text = _make_rich_rext(text=epilogue, markup_mode=markup_mode) console.print(Padding(Align(epilogue_text, pad=False), 1))
def list_files(self, folder: str = None, show_size: bool = False): """Create a tree displaying the files within the project.""" console = Console() # Make call to API try: response = requests.get( DDSEndpoint.LIST_FILES, params={ "subpath": folder, "show_size": show_size }, headers=self.token, ) except requests.exceptions.RequestException as err: raise SystemExit from err if not response.ok: console.print(f"Failed to get list of files: {response.text}") os._exit(0) # Get response try: resp_json = response.json() except simplejson.JSONDecodeError as err: raise SystemExit from err # Check if project empty if "num_items" in resp_json and resp_json["num_items"] == 0: console.print(f"[i]Project '{self.project}' is empty.[/i]") os._exit(0) # Get files files_folders = resp_json["files_folders"] # Warn user if there will be too many rows self.warn_if_many(count=len(files_folders)) # Sort the file/folders according to names sorted_projects = sorted(files_folders, key=lambda f: f["name"]) # Create tree tree_title = folder if folder is None: tree_title = f"Files/Directories in project: {self.project}" tree = Tree(f"[bold spring_green4]{tree_title}") if sorted_projects: # Get max length of file name max_string = max([len(x["name"]) for x in sorted_projects]) # Get max length of size string sizes = [ len(x["size"][0]) for x in sorted_projects if show_size and "size" in x ] max_size = max(sizes) if sizes else 0 # Add items to tree for x in sorted_projects: # Check if string is folder is_folder = x.pop("folder") # Att 1 for folders due to trailing / tab = th.TextHandler.format_tabs( string_len=len(x["name"]) + (1 if is_folder else 0), max_string_len=max_string, ) # Add formatting if folder and set string name line = "" if is_folder: line = "[bold deep_sky_blue3]" line += x["name"] + ("/" if is_folder else "") # Add size to line if option specified if show_size and "size" in x: line += f"{tab}{x['size'][0]}" # Define space between number and size format tabs_bf_format = th.TextHandler.format_tabs( string_len=len(x["size"][0]), max_string_len=max_size, tab_len=2) line += f"{tabs_bf_format}{x['size'][1]}" tree.add(line) console.print(Padding(tree, 1)) else: console.print(Padding(f"[i]No folder called '{folder}'[/i]", 1))
def list_files(self, folder: str = None, show_size: bool = False): """Create a tree displaying the files within the project.""" LOG.info(f"Listing files for project '{self.project}'") if folder: LOG.info(f"Showing files in folder '{escape(folder)}'") if folder is None: folder = "" # Make call to API try: response = requests.get( DDSEndpoint.LIST_FILES, params={"project": self.project}, json={"subpath": folder, "show_size": show_size}, headers=self.token, timeout=DDSEndpoint.TIMEOUT, ) except requests.exceptions.RequestException as err: raise exceptions.APIError( message=( f"Failed to get list of files in project '{self.project}'" + ( ": The database seems to be down." if isinstance(err, requests.exceptions.ConnectionError) else "." ) ) ) if not response.ok: raise exceptions.APIError(f"Failed to get list of files: '{response.text}'") # Get response try: resp_json = response.json() except simplejson.JSONDecodeError as err: raise exceptions.APIError(f"Could not decode JSON response: '{err}'") # Check if project empty if "num_items" in resp_json and resp_json["num_items"] == 0: raise exceptions.NoDataError(f"Project '{self.project}' is empty.") # Get files files_folders = resp_json["files_folders"] # Sort the file/folders according to names sorted_files_folders = sorted(files_folders, key=lambda f: f["name"]) # Create tree tree_title = escape(folder) or f"Files / directories in project: [green]{self.project}" tree = Tree(f"[bold magenta]{tree_title}") if not sorted_files_folders: raise exceptions.NoDataError(f"Could not find folder: '{escape(folder)}'") # Get max length of file name max_string = max([len(x["name"]) for x in sorted_files_folders]) # Get max length of size string max_size = max( [ len( dds_cli.utils.format_api_response( response=x["size"], key="Size", binary=self.binary ).split(" ", maxsplit=1)[0] ) for x in sorted_files_folders if show_size and "size" in x ], default=0, ) # Visible folders visible_folders = [] # Add items to tree for x in sorted_files_folders: # Check if string is folder is_folder = x.pop("folder") # Att 1 for folders due to trailing / tab = th.TextHandler.format_tabs( string_len=len(x["name"]) + (1 if is_folder else 0), max_string_len=max_string, ) # Add formatting if folder and set string name line = "" if is_folder: line = "[bold deep_sky_blue3]" visible_folders.append(x["name"]) line += escape(x["name"]) + ("/" if is_folder else "") # Add size to line if option specified if show_size and "size" in x: size = dds_cli.utils.format_api_response( response=x["size"], key="Size", binary=self.binary ) line += f"{tab}{size.split()[0]}" # Define space between number and size format tabs_bf_format = th.TextHandler.format_tabs( string_len=len(size), max_string_len=max_size, tab_len=2 ) line += f"{tabs_bf_format}{size.split()[1]}" tree.add(line) # Print output to stdout if len(files_folders) + 5 > dds_cli.utils.console.height: with dds_cli.utils.console.pager(): dds_cli.utils.console.print(Padding(tree, 1)) else: dds_cli.utils.console.print(Padding(tree, 1)) # Return variable return visible_folders
def test_repr(): padding = Padding("foo", (1, 2)) assert isinstance(repr(padding), str)
def test_indent(): indent_result = Padding.indent("test", 4) assert indent_result.top == 0 assert indent_result.right == 0 assert indent_result.bottom == 0 assert indent_result.left == 4
def __rich_console__(self, console: Console, options: ConsoleOptions) -> RenderResult: code = str(self.text).rstrip() syntax = Padding(Syntax(code, self.lexer_name, theme=self.theme), pad=(1, 4)) yield syntax
def log(self, request): title = Text() title.append(request.method, style="bold red") title.append(" ") path = request.path if len(path) > 50: path = request.path[:50] + "..." title.append(path, style="blue") headers_table = Table( title="[bold]HTTP Headers\n", title_justify="center", show_edge=False ) headers_table.add_column( "Header", justify="left", style="magenta", no_wrap=True ) headers_table.add_column( "Value", justify="right", style="cyan", ) for header, value in request.headers.items(): if header.lower() in {"content-type", "content-length"}: continue headers_table.add_row(header, value) local_time, utc_time = datetime.now(), datetime.utcnow() group = [ Text.assemble( ("Local Time: ", "bold"), local_time.strftime(TIME_FORMAT), " - ", ("UTC Time: ", "bold"), utc_time.strftime(TIME_FORMAT), justify="center", ), Text.assemble( ("Content Type: ", "bold"), (str(request.content_type), "italic magenta"), " - ", (request.length_in_human, "cyan"), ), Text.assemble( ("Client's IP/Port: ", "bold"), f"{request.client_address}:{request.client_port}", ), ] # Query Params if request.params: params_table = Table( title="[bold]Query Params[/bold] (accepts repeated)\n", title_justify="center", show_edge=False, ) params_table.add_column( "Param", justify="left", style="magenta", no_wrap=True ) params_table.add_column( "Value", justify="right", style="cyan", ) for param, values in request.params.items(): params_table.add_row(param, ",".join(values)) group.append(Padding(params_table, (1,))) # Headers group.append(Padding(headers_table, (1,))) # Request Body if "log_body" in self.args and self.args.log_body: if request.body: group += [ Padding("[bold]Request Body:[/bold]", (1,)), Syntax( request.body, pygments.lexers.get_lexer_for_mimetype( request.content_type ).name, word_wrap=True, ), ] else: group.append( Padding("[bold]Request Body: [/bold][italic]Empty.[/italic]", (1,)), ) # Display it all print(Panel(RenderGroup(*group), title=title, box=box.ROUNDED, highlight=True,))
def add_header(header, head=False): p = Padding("", (0, 0), style="black") if head: pns = Padding("", (0, 0), style="black") table.add_row(pns, pns, pns, pns, pns) table.add_row(Padding(header, (0, 0), style="bold yellow"), p, p, p, p)
def check_depfile(env, verbose, toolset, component, depfile): '''Perform basic checks on dependency files''' lPackage, lComponent = component if depfile is None: depfile = basename(lComponent) + ".dep" lPathMaker = Pathmaker(env.srcdir, env._verbosity) try: lParser = DepFileParser(toolset, lPathMaker) lParser.parse(lPackage, lComponent, depfile) except OSError as lExc: raise click.ClickException( "Failed to parse dep file - '{}'".format(lExc)) cprint() # N.B. Rest of this function is heavily based on implementation of 'dep report' command; assuming # that output of these 2 commands does not significantly diverge, might make sense to implement # command output in a separate function, that's invoked by both commands lCmdHeaders = [ 'path', 'flags', 'lib', ] # ['path', 'flags', 'package', 'component', 'map', 'lib'] lFilters = [] lPrepend = re.compile('(^|\n)') if verbose: cprint('Parsed commands', style='blue') for k in lParser.commands: cprint(f" + {k} ({len(lParser.commands[k])})") if not lParser.commands[k]: continue lCmdTable = Table(*lCmdHeaders, title=f"{k} ({len(lParser.commands[k])})") for lCmd in lParser.commands[k]: lRow = [ relpath(lCmd.filepath, env.srcdir), ','.join(lCmd.flags()), lCmd.lib, ] if lFilters and not all( [rxp.match(lRow[i]) for i, rxp in lFilters]): continue lCmdTable.add_row(*lRow) cprint(Padding.indent(lCmdTable, 4)) cprint('Resolved packages & components', style='blue') string = '' for pkg in sorted(lParser.packages): string += ' + %s (%d)\n' % (pkg, len(lParser.packages[pkg])) for cmp in sorted(lParser.packages[pkg]): string += ' > ' + str(cmp) + '\n' cprint(string) if lParser.unresolved_packages: cprint('Missing packages:', style='red') cprint(str(list(lParser.unresolved_packages))) lCNF = lParser.unresolved_components if lCNF: cprint('Missing components:', style='red') string = '' for pkg in sorted(lCNF): string += '+ %s (%d)\n' % (pkg, len(lCNF[pkg])) for cmp in sorted(lCNF[pkg]): string += ' > ' + str(cmp) + '\n' cprint(string) lFNF = lParser.unresolved_files if lFNF: cprint('Missing files:', style='red') lFNFTable = Table('path', 'included by') for pkg in sorted(lFNF): lCmps = lFNF[pkg] for cmp in sorted(lCmps): lPathExps = lCmps[cmp] for pathexp in sorted(lPathExps): lFNFTable.add_row( relpath(pathexp, env.srcdir), '\n'.join([ relpath(src, env.srcdir) for src in lPathExps[pathexp] ]), ) cprint(Padding.indent(lFNFTable, 4)) if lParser.unresolved_packages or lParser.unresolved_components or lParser.unresolved_files: raise click.ClickException( f"Cannot find 1 or more files referenced by depfile {lPathMaker.getPath(lPackage, lComponent, 'include', depfile)}" ) elif not verbose: cprint( f"No errors found in depfile {lPathMaker.getPath(lPackage, lComponent, 'include', depfile)}" )
def draw(self, title="Result"): console.rule("[bold red]" + title) console.print(Padding(self.tab, style="on #444444", pad=(1, 1, 1, 1))) console.rule("[bold red]" + title)
def make_test_card() -> Table: """Get a renderable that demonstrates a number of features.""" table = Table.grid(padding=1, pad_edge=True) table.title = "Rich features" table.add_column("Feature", no_wrap=True, justify="right", style="bold red") table.add_column("Demonstration") color_table = Table( box=None, expand=False, show_header=False, show_edge=False, pad_edge=False, padding=0, ) color_table.add_row(*(ColorBox(16 + color * 36) for color in range(6))) table.add_row( "Colors", RenderGroup( "[bold yellow]256[/] colors or [bold green]16.7 million[/] colors [blue](if supported by your terminal)[/].", Padding(color_table, (1, 0, 0, 0)), ), ) table.add_row( "Styles", "All ansi styles: [bold]bold[/], [dim]dim[/], [italic]italic[/italic], [underline]underline[/], [strike]strikethrough[/], [reverse]reverse[/], and even [blink]blink[/].", ) lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque in metus sed sapien ultricies pretium a at justo. Maecenas luctus velit et auctor maximus. Donec faucibus vel arcu id pretium." lorem_table = Table.grid(padding=1, collapse_padding=True) lorem_table.pad_edge = False lorem_table.add_row( Text(lorem, justify="left", style="green"), Text(lorem, justify="center", style="yellow"), Text(lorem, justify="right", style="blue"), Text(lorem, justify="full", style="red"), ) table.add_row( "Text", RenderGroup( Text.from_markup( """Word wrap text. Justify [green]left[/], [yellow]center[/], [blue]right[/] or [red]full[/].\n\n""" ), lorem_table, ), ) def comparison(renderable1, renderable2) -> Table: table = Table(show_header=False, pad_edge=False, box=None, expand=True) table.add_column("1", ratio=1) table.add_column("2", ratio=1) table.add_row(renderable1, renderable2) return table table.add_row( "CJK support", Panel("该库支持中文,日文和韩文文本!", expand=False, style="red", box=box.DOUBLE_EDGE,), ) emoji_example = ( "Render emoji code: :+1: :apple: :ant: :bear: :baguette_bread: :bus: " ) table.add_row("Emoji", comparison(Text(emoji_example), emoji_example)) markup_example = "[bold magenta]Rich[/] supports a simple [i]bbcode[/i] like [b]markup[/b], you can use to insert [yellow]color[/] and [underline]style[/]." table.add_row( "Console markup", comparison(Text(markup_example), markup_example), ) example_table = Table( title="Star Wars box office", show_header=True, header_style="bold magenta" ) example_table.add_column("Date", style="dim", no_wrap=True) example_table.add_column("Title") example_table.add_column("Production Budget", justify="right", no_wrap=True) example_table.add_column("Box Office", justify="right", no_wrap=True) example_table.add_row( "Dec 20, 2019", "Star Wars: The Rise of Skywalker", "$275,000,000", "$375,126,118", ) example_table.add_row( "May 25, 2018", "[red]Solo[/red]: A Star Wars Story", "$275,000,000", "$393,151,347", ) example_table.add_row( "Dec 15, 2017", "Star Wars Ep. VIII: The Last Jedi", "$262,000,000", "[bold]$1,332,539,889[/bold]", ) table.add_row("Tables", example_table) code = '''\ def iter_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: """Iterate and generate a tuple with a flag for last value.""" iter_values = iter(values) try: previous_value = next(iter_values) except StopIteration: return for value in iter_values: yield False, previous_value previous_value = value yield True, previous_value''' table.add_row("Syntax highlighting", Syntax(code, "python3", line_numbers=True)) markdown_example = """\ # Markdown Supports much of the *markdown*, __syntax__! - Headers - Basic formatting: **bold**, *italic*, `code` - Block quotes - Lists, and more... """ table.add_row("Markdown", comparison(markdown_example, Markdown(markdown_example))) table.add_row( "And more", """Progress bars, styled logging handler, tracebacks, etc...""" ) return table
from rich import print from rich.padding import Padding test = Padding("Hello", (2, 4), style="on blue", expand=False) print(test)
from rich.panel import Panel from rich.text import Text panel = Panel(Text("Hello", justify="right")) print(panel) from rich.console import Group panel_group = Group( Panel("Hello", style="on blue"), Panel("World", style="on red"), ) print(Panel(panel_group)) from rich.padding import Padding test = Padding("Hello", (0, 4)) print(test) import time from rich.live import Live from rich.table import Table table = Table() table.add_column("Row ID") table.add_column("Description") table.add_column("Level") with Live(table, refresh_per_second=4): # update 4 times a second to feel fluid for row in range(12):
def list_recursive(self, show_size: bool = False): """Recursively list project contents.""" @dataclass class FileTree: """Container class for holding information about the remote file tree.""" subtrees: List[Union["FileTree", Tuple[str, str]]] = None name: str = None def __api_call_list_files(folder: str): # Make call to API try: resp_json = requests.get( DDSEndpoint.LIST_FILES, params={"project": self.project}, json={"subpath": folder, "show_size": show_size}, headers=self.token, timeout=DDSEndpoint.TIMEOUT, ) except requests.exceptions.RequestException as err: raise exceptions.APIError(f"Problem with database response: '{err}'") resp_json = resp_json.json() if not "files_folders" in resp_json: raise exceptions.NoDataError(f"Could not find folder: '{folder}'") sorted_files_folders = sorted(resp_json["files_folders"], key=lambda f: f["name"]) if not sorted_files_folders: raise exceptions.NoDataError(f"Could not find folder: '{folder}'") return sorted_files_folders def __construct_file_tree(folder: str, basename: str) -> Tuple[FileTree, int, int]: """ Recurses through the project directories. Constructs a file tree by subsequent calls to the API """ tree = FileTree([], f"{basename}/") try: sorted_files_folders = __api_call_list_files(folder) except exceptions.NoDataError as e: if folder is None: raise exceptions.NoDataError( "No files or folders found for the specified project" ) else: raise exceptions.NoDataError(f"Could not find folder: '{escape(folder)}'") # Get max length of file name max_string = max([len(x["name"]) for x in sorted_files_folders]) # Get max length of size string max_size = max( [ len(x["size"].split(" ")[0]) for x in sorted_files_folders if show_size and "size" in x ], default=0, ) # Rich outputs precisely one line per file/folder for f in sorted_files_folders: is_folder = f.pop("folder") if not is_folder: tree.subtrees.append((escape(f["name"]), f.get("size") if show_size else None)) else: subtree, _max_string, _max_size = __construct_file_tree( os.path.join(folder, f["name"]) if folder else f["name"], f"[bold deep_sky_blue3]{escape(f['name'])}", ) # Due to indentation, the filename strings of # subdirectories are 4 characters deeper than # their parent directories max_string = max(max_string, _max_string + 4) max_size = max(max_size, _max_size) tree.subtrees.append(subtree) return tree, max_string, max_size def __construct_file_dict_tree(folder: str) -> dict: """ Recurses through the project directories. Constructs a file tree by subsequent calls to the API """ try: sorted_files_folders = __api_call_list_files(folder) except exceptions.NoDataError as e: if folder is None: raise exceptions.NoDataError( "No files or folders found for the specified project" ) else: raise exceptions.NoDataError(f"Could not find folder: '{folder}'") tree = {} for f in sorted_files_folders: is_folder = f.pop("folder") name = f["name"] if not is_folder: tree[name] = {"name": name, "is_folder": False, "children": {}} if show_size: tree[f["name"]]["size"] = f.get("size") else: children = __construct_file_dict_tree( os.path.join(folder, name) if folder else name ) tree[name] = {"name": name, "is_folder": True, "children": children} return tree def __construct_rich_tree( file_tree: FileTree, max_str: int, max_size: int, depth: int ) -> Tuple[Tree, int]: """Construct the rich tree from the file tree.""" tree = Tree(file_tree.name) tree_length = len(file_tree.subtrees) for node in file_tree.subtrees: if isinstance(node, FileTree): subtree, length = __construct_rich_tree(node, max_str, max_size, depth + 1) tree.add(subtree) tree_length += length else: line = node[0] if show_size and node[1] is not None: tab = th.TextHandler.format_tabs( string_len=len(node[0]), max_string_len=max_str - 4 * depth, ) line += f"{tab}{node[1].split()[0]}" # Define space between number and size format tabs_bf_format = th.TextHandler.format_tabs( string_len=len(node[1].split()[1]), max_string_len=max_size, tab_len=2, ) line += f"{tabs_bf_format}{node[1].split()[1]}" tree.add(line) return tree, tree_length if self.json: tree_dict = __construct_file_dict_tree(None) return tree_dict else: # We use two tree walks, one for file search and one for Rich tree # constructing, since it is difficult to compute the correct size # indentation without the whole tree file_tree, max_string, max_size = __construct_file_tree( None, f"[bold magenta]Files & directories in project: [green]{self.project}" ) tree, tree_length = __construct_rich_tree(file_tree, max_string, max_size, 0) # The first header is not accounted for by the recursion tree_length += 1 # Check if the tree is too large to be printed directly # and use a pager if that is the case if tree_length > dds_cli.utils.console.height: with dds_cli.utils.console.pager(): dds_cli.utils.console.print( Padding( tree, 1, ) ) else: dds_cli.utils.console.print( Padding( tree, 1, ) ) return None