# stretchable
[![PyPI - Version](https://img.shields.io/pypi/v/stretchable)](https://pypi.org/project/stretchable/)
[![Python Versions](https://img.shields.io/pypi/pyversions/stretchable)](https://www.python.org)
[![License](https://img.shields.io/github/license/mortencombat/stretchable?color=blue)](https://github.com/mortencombat/stretchable/blob/main/LICENSE)
[![GitHub issues](https://img.shields.io/github/issues/mortencombat/stretchable?logo=github)](https://github.com/mortencombat/stretchable/issues)
[![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/mortencombat/stretchable/build-publish.yml?logo=github)](https://github.com/mortencombat/stretchable/actions/workflows/build-publish.yml)
[![Documentation Status](https://readthedocs.org/projects/stretchable/badge/?version=stable)](https://stretchable.readthedocs.io/en/latest/?badge=stable)
[![Test results](https://gist.githubusercontent.com/mortencombat/901f1f1190ba5aff13164ede9d4c249f/raw/stretchable-tests.svg)](https://github.com/mortencombat/stretchable/actions/workflows/test.yml)
[![Test coverage](https://gist.githubusercontent.com/mortencombat/b121474745d15f92a295a0bdd7497529/raw/stretchable-coverage.svg)](https://github.com/mortencombat/stretchable/actions/workflows/test.yml)
**stretchable** is a layout library for Python that enables context-agnostic layout operations using CSS Block, [CSS Grid](https://css-tricks.com/snippets/css/complete-guide-grid/) and [Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/). Possible uses include UI layouts, page layouts for reports, complex plotting layouts, etc.
It implements Python bindings for [Taffy](https://github.com/dioxuslabs/taffy), an implementation of **CSS Block**, **Flexbox** and **CSS Grid** layout algorithms written in [Rust](https://www.rust-lang.org/). It was originally based on [Stretch](https://vislyhq.github.io/stretch/) (hence the name), but has since migrated to use Taffy. It is multi-platform and there are distributions available for Windows, Linux and macOS.
## Getting Started
**stretchable** is a Python package [hosted on PyPI](https://pypi.org/project/stretchable/). It can be installed using [pip](https://pip.pypa.io/en/stable/):
```console
python -m pip install stretchable
```
Building a tree of nodes and calculating the layout is as simple as:
```python
from stretchable import Edge, Node
from stretchable.style import AUTO, PCT
# Build node tree
root = Node(
margin=20,
size=(500, 300),
).add(
Node(border=5, size=(50 * PCT, AUTO)),
Node(key="child", padding=10 * PCT, size=50 * PCT),
)
# Compute layout
root.compute_layout()
# Get the second of the child nodes
child_node = root.find("/child")
content_box = child_node.get_box(Edge.CONTENT)
print(content_box)
# Box(x=300.0, y=50.0, width=150.0, height=50.0)
```
For more information and details, see the [documentation](https://stretchable.readthedocs.io/).
## Contributing
Contributions are welcomed. Please open an issue to clarify/plan implementation details prior to starting the work.
### Building
Install Rust with [rustup](https://rustup.rs/) and use `maturin develop` for development and `maturin build [--release]` to build.
### Documentation
To build documentation use `make html` (in `docs/` folder) or, to use live reloading: `sphinx-autobuild docs/source docs/build/html`
NOTE: Sometimes, you may need to run `make clean html` (in `docs/` folder) to ensure that all changes are included in the built html.
### Testing
Install test dependencies and invoke `pytest`. Note that there are ~900 tests, the majority of which are run using Selenium with the Chrome WebDriver, and the complete test suite can take ~30 minutes to complete. Use `pytest --lf` to only run the last-failed tests.
To run basic tests and ensure compatibility with a specific Python version, use Docker and the provided `Dockerfile`: `docker build . [--build-arg pyver=3.11]` (defaults to lowest supported Python version, currently 3.8).
## License
This work is released under the MIT license. A copy of the license is provided in the [LICENSE](https://github.com/mortencombat/stretchable/blob/main/LICENSE) file.
Raw data
{
"_id": null,
"home_page": null,
"name": "stretchable",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "flexbox, grid, block, stretch, css, layout",
"author": "Kenneth Trelborg Vestergaard",
"author_email": null,
"download_url": null,
"platform": null,
"description": "# stretchable\r\n\r\n[![PyPI - Version](https://img.shields.io/pypi/v/stretchable)](https://pypi.org/project/stretchable/)\r\n[![Python Versions](https://img.shields.io/pypi/pyversions/stretchable)](https://www.python.org)\r\n[![License](https://img.shields.io/github/license/mortencombat/stretchable?color=blue)](https://github.com/mortencombat/stretchable/blob/main/LICENSE)\r\n[![GitHub issues](https://img.shields.io/github/issues/mortencombat/stretchable?logo=github)](https://github.com/mortencombat/stretchable/issues)\r\n[![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/mortencombat/stretchable/build-publish.yml?logo=github)](https://github.com/mortencombat/stretchable/actions/workflows/build-publish.yml)\r\n[![Documentation Status](https://readthedocs.org/projects/stretchable/badge/?version=stable)](https://stretchable.readthedocs.io/en/latest/?badge=stable)\r\n[![Test results](https://gist.githubusercontent.com/mortencombat/901f1f1190ba5aff13164ede9d4c249f/raw/stretchable-tests.svg)](https://github.com/mortencombat/stretchable/actions/workflows/test.yml)\r\n[![Test coverage](https://gist.githubusercontent.com/mortencombat/b121474745d15f92a295a0bdd7497529/raw/stretchable-coverage.svg)](https://github.com/mortencombat/stretchable/actions/workflows/test.yml)\r\n\r\n**stretchable** is a layout library for Python that enables context-agnostic layout operations using CSS Block, [CSS Grid](https://css-tricks.com/snippets/css/complete-guide-grid/) and [Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/). Possible uses include UI layouts, page layouts for reports, complex plotting layouts, etc.\r\n\r\nIt implements Python bindings for [Taffy](https://github.com/dioxuslabs/taffy), an implementation of **CSS Block**, **Flexbox** and **CSS Grid** layout algorithms written in [Rust](https://www.rust-lang.org/). It was originally based on [Stretch](https://vislyhq.github.io/stretch/) (hence the name), but has since migrated to use Taffy. It is multi-platform and there are distributions available for Windows, Linux and macOS.\r\n\r\n## Getting Started\r\n\r\n**stretchable** is a Python package [hosted on PyPI](https://pypi.org/project/stretchable/). It can be installed using [pip](https://pip.pypa.io/en/stable/):\r\n\r\n```console\r\npython -m pip install stretchable\r\n```\r\n\r\nBuilding a tree of nodes and calculating the layout is as simple as:\r\n\r\n```python\r\nfrom stretchable import Edge, Node\r\nfrom stretchable.style import AUTO, PCT\r\n\r\n# Build node tree\r\nroot = Node(\r\n margin=20,\r\n size=(500, 300),\r\n).add(\r\n Node(border=5, size=(50 * PCT, AUTO)),\r\n Node(key=\"child\", padding=10 * PCT, size=50 * PCT),\r\n)\r\n\r\n# Compute layout\r\nroot.compute_layout()\r\n\r\n# Get the second of the child nodes\r\nchild_node = root.find(\"/child\")\r\ncontent_box = child_node.get_box(Edge.CONTENT)\r\nprint(content_box)\r\n# Box(x=300.0, y=50.0, width=150.0, height=50.0)\r\n\r\n```\r\n\r\nFor more information and details, see the [documentation](https://stretchable.readthedocs.io/).\r\n\r\n## Contributing\r\n\r\nContributions are welcomed. Please open an issue to clarify/plan implementation details prior to starting the work.\r\n\r\n### Building\r\n\r\nInstall Rust with [rustup](https://rustup.rs/) and use `maturin develop` for development and `maturin build [--release]` to build.\r\n\r\n### Documentation\r\n\r\nTo build documentation use `make html` (in `docs/` folder) or, to use live reloading: `sphinx-autobuild docs/source docs/build/html`\r\n\r\nNOTE: Sometimes, you may need to run `make clean html` (in `docs/` folder) to ensure that all changes are included in the built html.\r\n\r\n### Testing\r\n\r\nInstall test dependencies and invoke `pytest`. Note that there are ~900 tests, the majority of which are run using Selenium with the Chrome WebDriver, and the complete test suite can take ~30 minutes to complete. Use `pytest --lf` to only run the last-failed tests.\r\n\r\nTo run basic tests and ensure compatibility with a specific Python version, use Docker and the provided `Dockerfile`: `docker build . [--build-arg pyver=3.11]` (defaults to lowest supported Python version, currently 3.8).\r\n\r\n## License\r\n\r\nThis work is released under the MIT license. A copy of the license is provided in the [LICENSE](https://github.com/mortencombat/stretchable/blob/main/LICENSE) file.\r\n\n",
"bugtrack_url": null,
"license": null,
"summary": "Layout library for Python (based on Taffy, a rust-powered implementation of CSS Grid/Flexbox)",
"version": "1.1.6",
"project_urls": {
"Documentation": "https://stretchable.readthedocs.io/en/latest/",
"Homepage": "https://stretchable.readthedocs.io/en/latest/",
"Source": "https://github.com/mortencombat/stretchable",
"Tracker": "https://github.com/mortencombat/stretchable/issues"
},
"split_keywords": [
"flexbox",
" grid",
" block",
" stretch",
" css",
" layout"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "690d6ca23cffbd55e76bc31889d87700cc80728ca942d0f31bfc8a0c766d73d9",
"md5": "1c90f0e60de66a743cf2a20d8e2082cf",
"sha256": "fab2f1ca243a9b113fa4ed24418d9e85d1416f4a3fa083c6ef908b37a656883c"
},
"downloads": -1,
"filename": "stretchable-1.1.6-cp38-abi3-macosx_10_12_x86_64.whl",
"has_sig": false,
"md5_digest": "1c90f0e60de66a743cf2a20d8e2082cf",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.8",
"size": 454348,
"upload_time": "2024-10-26T14:38:42",
"upload_time_iso_8601": "2024-10-26T14:38:42.059998Z",
"url": "https://files.pythonhosted.org/packages/69/0d/6ca23cffbd55e76bc31889d87700cc80728ca942d0f31bfc8a0c766d73d9/stretchable-1.1.6-cp38-abi3-macosx_10_12_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "41d610a679e0f51800f38091db7c0ba37a23d60a76158d95d904b382c52db31f",
"md5": "f9f2972aa0f6f02791ddab903e7cfbf3",
"sha256": "7722ccef52e5e72a5deb5d8b81816a17a73e0b15923524e35cccb48502ab727d"
},
"downloads": -1,
"filename": "stretchable-1.1.6-cp38-abi3-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "f9f2972aa0f6f02791ddab903e7cfbf3",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.8",
"size": 422772,
"upload_time": "2024-10-26T14:38:43",
"upload_time_iso_8601": "2024-10-26T14:38:43.561276Z",
"url": "https://files.pythonhosted.org/packages/41/d6/10a679e0f51800f38091db7c0ba37a23d60a76158d95d904b382c52db31f/stretchable-1.1.6-cp38-abi3-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "9456bdd6163c90b0ca9352f8e559ecb6129cbc4f86e3983c1eb4f689bbd13c3e",
"md5": "23c5528ea5c57306573ee837b35ac13f",
"sha256": "9a3dc96ced7aa17dd0a3e21f0d7535db3928b6ca0f8888062bf8b1a8a933208a"
},
"downloads": -1,
"filename": "stretchable-1.1.6-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
"has_sig": false,
"md5_digest": "23c5528ea5c57306573ee837b35ac13f",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.8",
"size": 463765,
"upload_time": "2024-10-26T14:38:44",
"upload_time_iso_8601": "2024-10-26T14:38:44.909086Z",
"url": "https://files.pythonhosted.org/packages/94/56/bdd6163c90b0ca9352f8e559ecb6129cbc4f86e3983c1eb4f689bbd13c3e/stretchable-1.1.6-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "81f603dad639b923295ebadc436126fb38edefd7557e06eb6aa3d2b00fd2a2c7",
"md5": "102d6fb3fd081c39eebea2eb5ed3d231",
"sha256": "a607085573548facaf62e9367fbdd103d4d9761cea965927a02d691476123730"
},
"downloads": -1,
"filename": "stretchable-1.1.6-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "102d6fb3fd081c39eebea2eb5ed3d231",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.8",
"size": 490924,
"upload_time": "2024-10-26T14:38:46",
"upload_time_iso_8601": "2024-10-26T14:38:46.365115Z",
"url": "https://files.pythonhosted.org/packages/81/f6/03dad639b923295ebadc436126fb38edefd7557e06eb6aa3d2b00fd2a2c7/stretchable-1.1.6-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "42dfd11c52c660f8f39b4a45409c0827fd8ad9b73d74208bce9755cafde4ee36",
"md5": "f143b59e50ad58ae2e5b67aa6119a931",
"sha256": "529f023057178a37e6078d82f9494890ca9683c39dfb047238ec6958ffc289cc"
},
"downloads": -1,
"filename": "stretchable-1.1.6-cp38-abi3-musllinux_1_2_aarch64.whl",
"has_sig": false,
"md5_digest": "f143b59e50ad58ae2e5b67aa6119a931",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.8",
"size": 643907,
"upload_time": "2024-10-26T14:38:48",
"upload_time_iso_8601": "2024-10-26T14:38:48.186369Z",
"url": "https://files.pythonhosted.org/packages/42/df/d11c52c660f8f39b4a45409c0827fd8ad9b73d74208bce9755cafde4ee36/stretchable-1.1.6-cp38-abi3-musllinux_1_2_aarch64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "9ad560844f8d8b6f109ed1e0b4681070f58072d38f6146aa2f66dff62371c085",
"md5": "550c0d29290d643324d6b57f72b69314",
"sha256": "534e5c8745849bebfc6990384a46af01b28fa883959986fdc274c3821179131c"
},
"downloads": -1,
"filename": "stretchable-1.1.6-cp38-abi3-musllinux_1_2_x86_64.whl",
"has_sig": false,
"md5_digest": "550c0d29290d643324d6b57f72b69314",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.8",
"size": 645518,
"upload_time": "2024-10-26T14:38:49",
"upload_time_iso_8601": "2024-10-26T14:38:49.866971Z",
"url": "https://files.pythonhosted.org/packages/9a/d5/60844f8d8b6f109ed1e0b4681070f58072d38f6146aa2f66dff62371c085/stretchable-1.1.6-cp38-abi3-musllinux_1_2_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "67375315d811c6f3d270fb9bcfabb610f4238d8ef09ba5c66315479cb22e8355",
"md5": "4fd3193cd71f0c9087832e570d5da996",
"sha256": "bbb3b89e9981ba925ef5487e5b7a3efc82dfe2eae15e2fe0760393f4e1c6aa6a"
},
"downloads": -1,
"filename": "stretchable-1.1.6-cp38-abi3-win32.whl",
"has_sig": false,
"md5_digest": "4fd3193cd71f0c9087832e570d5da996",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.8",
"size": 321051,
"upload_time": "2024-10-26T14:38:51",
"upload_time_iso_8601": "2024-10-26T14:38:51.033664Z",
"url": "https://files.pythonhosted.org/packages/67/37/5315d811c6f3d270fb9bcfabb610f4238d8ef09ba5c66315479cb22e8355/stretchable-1.1.6-cp38-abi3-win32.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "7507758120f9f65b0573c03e0ee67a7ae577cfedc362b19602fbd54c21bf4cf0",
"md5": "11e8ebce8387a3fdfaf5d5aaa74a6681",
"sha256": "a933fcd13d96a55cd8c54a05f0affdd3e306a4775a87cf9c72e1e47e9f29ebf2"
},
"downloads": -1,
"filename": "stretchable-1.1.6-cp38-abi3-win_amd64.whl",
"has_sig": false,
"md5_digest": "11e8ebce8387a3fdfaf5d5aaa74a6681",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.8",
"size": 330248,
"upload_time": "2024-10-26T14:38:52",
"upload_time_iso_8601": "2024-10-26T14:38:52.792018Z",
"url": "https://files.pythonhosted.org/packages/75/07/758120f9f65b0573c03e0ee67a7ae577cfedc362b19602fbd54c21bf4cf0/stretchable-1.1.6-cp38-abi3-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "6d3ae264b9e02943b222998ba04ed0225ca9be4ddb606dac63b4f436e93911fb",
"md5": "b2d541461a8cc9aa69f1a26b64cb0bc4",
"sha256": "eb3e78ea89549acbe98966cacbdcd6a01fe83a5806f103b0fae6866ff3e7c345"
},
"downloads": -1,
"filename": "stretchable-1.1.6-cp38-abi3-win_arm64.whl",
"has_sig": false,
"md5_digest": "b2d541461a8cc9aa69f1a26b64cb0bc4",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.8",
"size": 306438,
"upload_time": "2024-10-26T14:38:53",
"upload_time_iso_8601": "2024-10-26T14:38:53.982489Z",
"url": "https://files.pythonhosted.org/packages/6d/3a/e264b9e02943b222998ba04ed0225ca9be4ddb606dac63b4f436e93911fb/stretchable-1.1.6-cp38-abi3-win_arm64.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-26 14:38:42",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "mortencombat",
"github_project": "stretchable",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "stretchable"
}