Stretchable
raw JSON → 1.1.8 verified Sat May 09 auth: no python
A Python layout library that uses Taffy, a Rust-powered implementation of CSS Grid and Flexbox, to compute layouts declaratively. Current version is 1.1.8, supporting Python >=3.8. Release cadence is irregular, approximately bi-monthly.
pip install stretchable Common errors
error TypeError: 'int' object is not callable ↓
cause Mistaking Auto for a function; Auto is a constant sentinel, not a callable.
fix
Use Auto directly: size={'width': Auto, 'height': 100}.
error AttributeError: 'NoneType' object has no attribute 'left' ↓
cause Calling tree.get_layout() for a node that hasn't been added to the tree or layout not computed.
fix
Ensure node is added as child via root.add_child(node) and call tree.compute_layout() before get_layout().
error ModuleNotFoundError: No module named 'stretchable' ↓
cause stretchable not installed or installed in a different environment.
fix
Run 'pip install stretchable'. If using virtual environments, ensure it is activated.
Warnings
gotcha Nodes must be added as children before calling tree.compute_layout(), otherwise they are not part of the layout calculation. ↓
fix Call root.add_child(child) before tree.compute_layout().
breaking Upgrade to v1.1.0 introduced breaking changes due to Taffy 0.5.1 upgrade. CSS Block layout and overflow support were added; some APIs changed (e.g., measure function signatures). ↓
fix Refer to migration notes in GitHub releases. For custom measure functions, ensure they match the new signature (width, height, available_width, available_height).
gotcha The size property in Style expects a dictionary, not a tuple. Common mistake: using size=(100, 50) instead of size={"width": 100, "height": 50}. ↓
fix Use dictionary format: size={'width': 100, 'height': 50}.
deprecated Direct assignment to Node.style (e.g., node.style = new_style) is deprecated after v1.1.1. Use setter method or property assignment carefully. ↓
fix Use node.style_setter() or modify individual properties of node.style (e.g., node.style.flex_direction = 'row').
Imports
- Auto
from stretchable import Auto - Node
from stretchable import Node - LayoutTree
from stretchable import LayoutTree - Style
from stretchable import Style - Layout
from stretchable import Layout
Quickstart
from stretchable import Node, LayoutTree, Style
# Create a root node with flexbox layout
root = Node(style=Style(size={"width": 100, "height": 100}, display="flex", flex_direction="column", gap=10))
child1 = Node(style=Style(size={"width": 50, "height": 30}))
child2 = Node(style=Style(size={"width": 50, "height": 30}))
# Build and compute layout
tree = LayoutTree(root)
root.add_child(child1)
root.add_child(child2)
tree.compute_layout()
# Print layout of child1
layout = tree.get_layout(child1)
print(f"Child1: left={layout.left}, top={layout.top}, width={layout.width}, height={layout.height}")