Python TUI framework with mouse support, modular widget system, customizable and rapid terminal markup language and more
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
PyTermGUI provides comprehensive file loading and serialization capabilities for widget configuration management, including YAML and JSON support for creating widgets from configuration files and persisting widget states.
Base file loading system with support for different formats and widget namespace management.
class FileLoader:
"""Base file loader for widget configuration."""
def __init__(self):
"""Initialize file loader."""
def load(self, path: str) -> "WidgetNamespace":
"""
Load widget configuration from file.
Parameters:
- path (str): Path to configuration file
Returns:
WidgetNamespace containing loaded widgets
"""
def save(self, namespace: "WidgetNamespace", path: str):
"""
Save widget namespace to file.
Parameters:
- namespace (WidgetNamespace): Widgets to save
- path (str): Output file path
"""
class YamlLoader(FileLoader):
"""YAML file loader for widget configuration."""
def load(self, path: str) -> "WidgetNamespace":
"""
Load widgets from YAML file.
Parameters:
- path (str): Path to YAML file
Returns:
WidgetNamespace with loaded widgets
Requires:
PyYAML package (pip install PyYAML)
"""
class JsonLoader(FileLoader):
"""JSON file loader for widget configuration."""
def load(self, path: str) -> "WidgetNamespace":
"""
Load widgets from JSON file.
Parameters:
- path (str): Path to JSON file
Returns:
WidgetNamespace with loaded widgets
"""Container for managing collections of loaded widgets with name-based access.
class WidgetNamespace:
"""Container for loaded widget configurations."""
def __init__(self, widgets: dict[str, Widget] = None):
"""
Create widget namespace.
Parameters:
- widgets (dict, optional): Named widget collection
"""
def __getitem__(self, name: str) -> Widget:
"""Get widget by name."""
def __setitem__(self, name: str, widget: Widget):
"""Set named widget."""
def __contains__(self, name: str) -> bool:
"""Check if widget name exists."""
@property
def widgets(self) -> dict[str, Widget]:
"""Get all widgets as dictionary."""
def add(self, name: str, widget: Widget):
"""Add named widget to namespace."""
def remove(self, name: str) -> Widget:
"""Remove and return named widget."""
def list_names(self) -> list[str]:
"""Get list of all widget names."""Widget serialization for saving and loading widget states and configurations.
class Serializer:
"""Widget serialization and deserialization system."""
def __init__(self):
"""Initialize serializer."""
def dump(self, widget: Widget) -> dict:
"""
Serialize widget to dictionary.
Parameters:
- widget (Widget): Widget to serialize
Returns:
Dictionary representation of widget
"""
def load(self, data: dict) -> Widget:
"""
Deserialize widget from dictionary.
Parameters:
- data (dict): Serialized widget data
Returns:
Reconstructed widget instance
"""
def dump_to_file(self, widget: Widget, filename: str):
"""Save widget to file."""
def load_from_file(self, filename: str) -> Widget:
"""Load widget from file."""
# Global serializer instance
serializer: SerializerExample YAML widget configuration format:
# widgets.yaml
main_window:
type: Window
title: "My Application"
width: 60
height: 20
widgets:
- type: Label
value: "[bold]Welcome to PyTermGUI"
- type: Container
widgets:
- type: Button
label: "Click Me"
onclick: "handle_click"
- type: InputField
prompt: "Enter text:"
value: ""
settings_dialog:
type: Window
title: "Settings"
width: 40
height: 15
widgets:
- type: Checkbox
label: "Enable sound"
checked: true
- type: Slider
min_value: 0
max_value: 100
value: 50Example JSON widget configuration format:
{
"main_form": {
"type": "Container",
"width": 50,
"widgets": [
{
"type": "Label",
"value": "[210 bold]User Registration"
},
{
"type": "InputField",
"prompt": "Username:",
"id": "username_field"
},
{
"type": "InputField",
"prompt": "Password:",
"id": "password_field"
},
{
"type": "Button",
"label": "Register",
"onclick": "handle_register"
}
]
}
}import pytermgui as ptg
# Load widgets from YAML file
loader = ptg.YamlLoader()
namespace = loader.load("widgets.yaml")
# Access loaded widgets by name
main_window = namespace["main_window"]
settings_dialog = namespace["settings_dialog"]
# Use in window manager
with ptg.WindowManager() as manager:
manager.add(main_window)import pytermgui as ptg
# Load from JSON configuration
loader = ptg.JsonLoader()
namespace = loader.load("forms.json")
# Get specific widget
form = namespace["main_form"]
# Add to application
with ptg.WindowManager() as manager:
window = ptg.Window(form, title="Registration")
manager.add(window)import pytermgui as ptg
# Create widget hierarchy
container = ptg.Container(
"[bold]Settings Panel",
"",
ptg.Checkbox(checked=True, label="Enable notifications"),
ptg.Slider(value=75, min_value=0, max_value=100),
ptg.Button("Save", lambda btn: print("Saved")),
width=40
)
# Serialize widget to dictionary
widget_data = ptg.serializer.dump(container)
print(widget_data)
# Save to file
ptg.serializer.dump_to_file(container, "settings.json")
# Later, load widget back
restored_container = ptg.serializer.load_from_file("settings.json")import pytermgui as ptg
def create_form_from_config(config_file):
"""Create form widgets from configuration."""
loader = ptg.JsonLoader()
namespace = loader.load(config_file)
forms = {}
for name, widget in namespace.widgets.items():
if isinstance(widget, ptg.Container):
forms[name] = widget
return forms
# Load multiple forms
forms = create_form_from_config("forms.json")
# Create tabbed interface
current_form = "login"
def switch_form(form_name):
global current_form
current_form = form_name
# Update display logic here
# Use forms in application
with ptg.WindowManager() as manager:
window = ptg.Window(
forms[current_form],
title="Forms Demo"
)
manager.add(window)import pytermgui as ptg
# Define callback functions
def handle_submit(button):
print("Form submitted!")
def handle_cancel(button):
print("Form cancelled!")
# Callback registry for configuration files
CALLBACKS = {
"handle_submit": handle_submit,
"handle_cancel": handle_cancel
}
def load_with_callbacks(config_file):
"""Load widgets and bind callbacks."""
loader = ptg.JsonLoader()
namespace = loader.load(config_file)
# Process widgets to bind callbacks
for widget in namespace.widgets.values():
bind_callbacks_recursive(widget)
return namespace
def bind_callbacks_recursive(widget):
"""Recursively bind callbacks to widgets."""
if hasattr(widget, 'onclick') and isinstance(widget.onclick, str):
# Replace string callback name with actual function
callback_name = widget.onclick
if callback_name in CALLBACKS:
widget.onclick = CALLBACKS[callback_name]
# Process child widgets
if hasattr(widget, 'widgets'):
for child in widget.widgets:
bind_callbacks_recursive(child)
# Usage
namespace = load_with_callbacks("interface.json")import pytermgui as ptg
class StatefulForm:
"""Form that can save and restore its state."""
def __init__(self):
self.form = ptg.Container(
"[bold]Stateful Form",
"",
ptg.InputField(prompt="Name:", id="name"),
ptg.InputField(prompt="Email:", id="email"),
ptg.Checkbox(id="newsletter", label="Newsletter"),
"",
ptg.Button("Save State", self.save_state),
ptg.Button("Load State", self.load_state),
width=50
)
def save_state(self, button):
"""Save current form state."""
ptg.serializer.dump_to_file(self.form, "form_state.json")
print("State saved!")
def load_state(self, button):
"""Restore form state."""
try:
restored_form = ptg.serializer.load_from_file("form_state.json")
# Update current form with restored values
self.update_form_values(restored_form)
print("State loaded!")
except FileNotFoundError:
print("No saved state found")
def update_form_values(self, restored_form):
"""Update form with restored values."""
# Implementation depends on specific widget ID matching
for widget in restored_form.widgets:
if hasattr(widget, 'id') and widget.id:
current_widget = self.find_widget_by_id(widget.id)
if current_widget:
# Copy values from restored widget
if hasattr(widget, 'value'):
current_widget.value = widget.value
if hasattr(widget, 'checked'):
current_widget.checked = widget.checked
# Usage
form = StatefulForm()Install with Tessl CLI
npx tessl i tessl/pypi-pytermgui