Rich Python Trees
You can go to my Github profile to see an example use-case for rich. Rich can also render nested trees, which can give a very satisfying result.
Here's the implementation on my Github, it's an re-implementation from the creators profile.
from rich.console import Console
from rich.tree import Tree
console = Console(record=True, width=100)
tree = Tree("🙂 [link=https://koaning.io]Vincent D. Warmerdam", guide_style="bold bright_black")
python_tree = tree.add("📦 Open Source Packages", guide_style="bright_black")
python_tree.add("[bold link=https://scikit-lego.netlify.app/]scikit-lego[/] - [bright_black]lego bricks for sklearn")
python_tree.add("[bold link=https://koaning.github.io/human-learn/]human-learn[/] - [bright_black]rule-based components for sklearn")
online_tree = tree.add("⭐ Online Projects", guide_style="bright_black")
online_tree.add("[bold link=https://koaning.io]koaning.io[/] - [bright_black]personal blog")
online_tree.add("[bold link=https://calmcode.io]calmcode.io[/] - [bright_black]dev education service")
talk_tree = tree.add("🎙️ Popular Talks", guide_style="bright_black")
talk_tree.add("[bold link=https://youtu.be/qcrR-Hd0LhI?t=542]Optimal Benchmarks and Other Failures[/]")
talk_tree.add("[bold link=https://www.youtube.com/watch?v=nJAmN6gWdK8]Playing by the Rules-Based-Systems[/]")
employer_tree = tree.add("👨💻 Employer", guide_style="bright_black")
employer_tree.add("[bold link=https://rasa.com]Rasa[/] - [bright_black]conversational software")
console.print(tree)
console.print("")
console.print("[green]Follow me on twitter [bold link=https://twitter.com/fishnets88]@fishnets88[/]")
CONSOLE_HTML_FORMAT = """\
<pre style="font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace">{code}</pre>
"""
console.save_html("README.md", inline_styles=True, code_format=CONSOLE_HTML_FORMAT)
Filestructures
Another great use-case for these trees is to use them to visualise the file structure. I have a script in my snippets library for just this use-case. Here's an example command.
python tree.py dirname
Here's the implementation of tree.py
.
"""
Simple tree-render from the command line.
Originally from: https://github.com/willmcgugan/rich/blob/master/examples/tree.py
"""
import os
import pathlib
import sys
from rich import print
from rich.filesize import decimal
from rich.markup import escape
from rich.text import Text
from rich.tree import Tree
def walk_directory(directory: pathlib.Path, tree: Tree) -> None:
"""Recursively build a Tree with directory contents."""
# Sort dirs first then by filename
paths = sorted(
pathlib.Path(directory).iterdir(),
key=lambda path: (path.is_file(), path.name.lower()),
)
for path in paths:
# Remove hidden files
if path.name.startswith("."):
continue
if path.parts[-1] == "venv":
continue
if path.is_dir():
style = "dim" if path.name.startswith("__") else ""
branch = tree.add(
f"[bold magenta]:open_file_folder: [link file://{path}]{escape(path.name)}",
style=style,
guide_style=style,
)
walk_directory(path, branch)
else:
text_filename = Text(path.name, "green")
text_filename.highlight_regex(r"\..*$", "bold red")
text_filename.stylize(f"link file://{path}")
file_size = path.stat().st_size
text_filename.append(f" ({decimal(file_size)})", "blue")
icon = "🐍 " if path.suffix == ".py" else "📄 "
tree.add(Text(icon) + text_filename)
try:
directory = os.path.abspath(sys.argv[1])
except IndexError:
print("[b]Usage:[/] python tree.py <DIRECTORY>")
else:
tree = Tree(
f":open_file_folder: [link file://{directory}]{directory}",
guide_style="bold bright_blue",
)
walk_directory(pathlib.Path(directory), tree)
print(tree)
Here's what the result might look like.
📂 /Users/vincent/Development/memo/build
┣━━ 📂 bdist.macosx-10.9-x86_64
┗━━ 📂 lib
┣━━ 📂 memo
┃ ┣━━ 🐍 __init__.py (422 bytes)
┃ ┣━━ 🐍 _base.py (2.7 kB)
┃ ┣━━ 🐍 _error.py (795 bytes)
┃ ┣━━ 🐍 _grid.py (1.3 kB)
┃ ┣━━ 🐍 _http.py (868 bytes)
┃ ┣━━ 🐍 _runner.py (5.1 kB)
┃ ┗━━ 🐍 _util.py (1.3 kB)
┗━━ 📂 tests
┣━━ 🐍 __init__.py (0 bytes)
┣━━ 🐍 conftest.py (0 bytes)
┣━━ 🐍 test_docs.py (690 bytes)
┣━━ 🐍 test_grid.py (428 bytes)
┣━━ 🐍 test_memfile.py (1.6 kB)
┣━━ 🐍 test_memlist.py (1.6 kB)
┗━━ 🐍 test_runner.py (2.5 kB)
Note the nice snake emoji's that render when it finds a python file!