{"id":29473433,"url":"https://github.com/betterbuiltfool/weaktree","last_synced_at":"2025-09-14T07:08:14.437Z","repository":{"id":303780927,"uuid":"1016657733","full_name":"BetterBuiltFool/weaktree","owner":"BetterBuiltFool","description":"Provides a tree structure that doesn't keep its data alive, and self prunes.","archived":false,"fork":false,"pushed_at":"2025-07-09T10:46:22.000Z","size":5,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-09T11:53:16.148Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BetterBuiltFool.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-09T10:31:52.000Z","updated_at":"2025-07-09T10:46:26.000Z","dependencies_parsed_at":"2025-07-09T12:03:31.737Z","dependency_job_id":null,"html_url":"https://github.com/BetterBuiltFool/weaktree","commit_stats":null,"previous_names":["betterbuiltfool/weaktree"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/BetterBuiltFool/weaktree","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BetterBuiltFool%2Fweaktree","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BetterBuiltFool%2Fweaktree/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BetterBuiltFool%2Fweaktree/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BetterBuiltFool%2Fweaktree/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BetterBuiltFool","download_url":"https://codeload.github.com/BetterBuiltFool/weaktree/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BetterBuiltFool%2Fweaktree/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265313474,"owners_count":23745190,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-14T15:38:48.740Z","updated_at":"2025-08-22T06:33:34.837Z","avatar_url":"https://github.com/BetterBuiltFool.png","language":"Python","readme":"\u003c!-- Improved compatibility of back to top link: See: https://github.com/othneildrew/Best-README-Template/pull/73 --\u003e\n\u003ca id=\"readme-top\"\u003e\u003c/a\u003e\n\u003c!--\n*** Thanks for checking out the Best-README-Template. If you have a suggestion\n*** that would make this better, please fork the repo and create a pull request\n*** or simply open an issue with the tag \"enhancement\".\n*** Don't forget to give the project a star!\n*** Thanks again! Now go create something AMAZING! :D\n--\u003e\n\n\n\n\u003c!-- PROJECT SHIELDS --\u003e\n\u003c!--\n*** I'm using markdown \"reference style\" links for readability.\n*** Reference links are enclosed in brackets [ ] instead of parentheses ( ).\n*** See the bottom of this document for the declaration of the reference variables\n*** for contributors-url, forks-url, etc. This is an optional, concise syntax you may use.\n*** https://www.markdownguide.org/basic-syntax/#reference-style-links\n--\u003e\n[![Contributors][contributors-shield]][contributors-url]\n[![Forks][forks-shield]][forks-url]\n[![Stargazers][stars-shield]][stars-url]\n[![Issues][issues-shield]][issues-url]\n[![MIT License][license-shield]][license-url]\n\u003c!--\n[![LinkedIn][linkedin-shield]][linkedin-url]\n--\u003e\n\n\n\n\u003c!-- PROJECT LOGO --\u003e\n\u003cbr /\u003e\n\u003c!--\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://github.com/BetterBuiltFool/weaktree\"\u003e\n    \u003cimg src=\"images/logo.png\" alt=\"Logo\" width=\"80\" height=\"80\"\u003e\n  \u003c/a\u003e\n--\u003e\n\n\u003ch3 align=\"center\"\u003eWeaktree\u003c/h3\u003e\n\n  \u003cp align=\"center\"\u003e\n    Model Data Trees Without Worrying About Lifetimes\n    \u003cbr /\u003e\n    \u003ca href=\"https://github.com/BetterBuiltFool/weaktree\"\u003e\u003cstrong\u003eExplore the docs »\u003c/strong\u003e\u003c/a\u003e\n    \u003cbr /\u003e\n    \u003cbr /\u003e\n    \u003c!--\n    \u003ca href=\"https://github.com/BetterBuiltFool/weaktree\"\u003eView Demo\u003c/a\u003e\n    ·\n    --\u003e\n    \u003ca href=\"https://github.com/BetterBuiltFool/weaktree/issues/new?labels=bug\u0026template=bug-report---.md\"\u003eReport Bug\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/BetterBuiltFool/weaktree/issues/new?labels=enhancement\u0026template=feature-request---.md\"\u003eRequest Feature\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n\n\n\u003c!-- TABLE OF CONTENTS --\u003e\n\u003cdetails\u003e\n  \u003csummary\u003eTable of Contents\u003c/summary\u003e\n  \u003col\u003e\n    \u003cli\u003e\n      \u003ca href=\"#about-the-project\"\u003eAbout The Project\u003c/a\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\n      \u003ca href=\"#getting-started\"\u003eGetting Started\u003c/a\u003e\n      \u003cul\u003e\n        \u003cli\u003e\u003ca href=\"#installation\"\u003eInstallation\u003c/a\u003e\u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#usage\"\u003eUsage\u003c/a\u003e\u003c/li\u003e\n      \u003cul\u003e\n        \u003cli\u003e\u003ca href=\"#creating-weaktrees\"\u003eCreating WeakTrees\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#accessing-data\"\u003eAccessing Data\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#cleanup\"\u003eCleanup\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#tree-iteration\"\u003eTree Iteration\u003c/a\u003e\u003c/li\u003e\n      \u003c/ul\u003e\n    \u003cli\u003e\u003ca href=\"#api-reference\"\u003eAPI Reference\u003c/a\u003e\u003c/li\u003e\n    \u003c!-- \u003cli\u003e\u003ca href=\"#roadmap\"\u003eRoadmap\u003c/a\u003e\u003c/li\u003e --\u003e\n    \u003c!--\u003cli\u003e\u003ca href=\"#contributing\"\u003eContributing\u003c/a\u003e\u003c/li\u003e--\u003e\n    \u003cli\u003e\u003ca href=\"#license\"\u003eLicense\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#contact\"\u003eContact\u003c/a\u003e\u003c/li\u003e\n    \u003c!-- \u003cli\u003e\u003ca href=\"#acknowledgments\"\u003eAcknowledgments\u003c/a\u003e\u003c/li\u003e --\u003e\n  \u003c/ol\u003e\n\u003c/details\u003e\n\n\n\n\u003c!-- ABOUT THE PROJECT --\u003e\n## About The Project\n\n\u003c!--\n[![Product Name Screen Shot][product-screenshot]](https://example.com)\n--\u003e\n\nWeaktree provides tree nodes that don't make strong references to their data, and can clean themselves up when their data expires. WeakTreeNodes also provide several handy iteration method for easy traversal.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\u003c!-- GETTING STARTED --\u003e\n## Getting Started\n\nWeaktree is written in pure python, with no system dependencies, and should be OS-agnostic.\n\n### Installation\n\nWeaktree can be installed from the [PyPI][pypi-url] using [pip][pip-url]:\n\n```sh\npip install weaktree\n```\n\nand can be imported for use with:\n```python\nimport weaktree\n```\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\n\u003c!-- USAGE EXAMPLES --\u003e\n## Usage\n\nTrees are built out of WeakTreeNodes. WeakTreeNodes possess a `trunk` and `branches`, which are used to define the hierarchy of the tree. Nodes with a trunk of `None` are considered root nodes.\n\n### Creating WeakTrees\n\nRoot nodes can be created with the WeakTreeNode constructor.\n\n```python\nroot = WeakTreeNode(some_object)\n```\n\nBranches can be added either by creating new nodes the same way and passing another node as the `trunk`, or by using WeakTreeNode.add_branch().\n\n```python\nroot.add_branch(another_object)\n```\n\nWeakTreeNode.add_branch() returns the new node, so they can be chained.\n\n```python\nroot.add_branch(third_object).add_branch(fourth_object).add_branch(fifth_object)\n```\n\nTrees can also be reorganized by assigning to the `trunk` property.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n### Accessing Data\n\nThe stored data of a Node is accessed by the `data` property. This will dereference the weakref, and return either the data object, or None if the object has expired.\n\nAlternatively, if iterating over the tree by the `values()` method, the iterand will be the value from `data`.\n\n\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n### Cleanup\n\nWeakTreeNodes possess the `cleanup_mode` property. This is used to how the tree modifies itself when a Node's data reference expires. These values are accessible as constants in the WeakTreeNode class.\n\n#### Prune\n\nWhen the node expires, all descending nodes are removed from the tree.\n\nNote: If there are strong references to those nodes elsewhere, they will be kept alive and the branches will not be fully unwound. However, they will no longer be reachable from other nodes in the tree.\n\n#### Reparent\n\nWhen the node expires, shift its branches up to its trunk. All descending nodes will be shifted up in the hierarchy.\n\n#### No cleanup\n\nWhen a node expires, leave the tree intact. Instead, the node will be \"empty\" and report a value of `None`.\n\n#### Default\n\nA node will do whatever its trunk node would do when it expires. For root nodes, this will be `prune`.\n\n\n#### Callbacks\n\nWeakTreeNodes feature an optional callback parameter for each node. The callback must take a weakreference object as its parameter. This will be the reference to the data value, just before it expires.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n### Tree Iteration\n\nWeakTreeNodes provide several features to simplify traversal. All branch iteration follows insertion order of the branch nodes.\n\nYou can control the type of data provided in the iteration:\n\n#### By Nodes\n\nBy using WeakTreeNode.nodes() or by directly iteration over the tree, you can traverse over the nodes themselves.\nThis is comparable to the `keys()` method of dictionaries.\n\nExample:\n```python\nroot = WeakTreeNode(some_object)\n\nroot.add_branch(one_fish).add_branch(two_fish)\n\nroot.add_branch(red_fish).add_branch(blue_fish)\n\nfor node in root.nodes():  # \u003c- Same as `for node in root:`\n    print(node)\n\n    # Expected order: Node(some_object), Node(one_fish), Node(red_fish), Node(two_fish), Node(blue_fish)\n\n```\n\n#### By Values\n\nBy using WeakTreeNode.values(), you can iterate over the values of the nodes. This is comparable to the method of the same name in dictionaries.\n\nExample:\n```python\nroot = WeakTreeNode(some_object)\n\nroot.add_branch(one_fish).add_branch(two_fish)\n\nroot.add_branch(red_fish).add_branch(blue_fish)\n\nfor node in root.values():\n    print(node)\n\n    # Expected output: some_object, one_fish, red_fish, two_fish, blue_fish\n\n```\n\n\n#### By Items\n\nWeakTreeNode.items() provides an iterable that gives the pairs of nodes and values. This is comparable to the method of the same name in dictionaries.\n\n\nYou can also control _how_ the iteration traverses the tree.\n\n#### By Breadth\n\nBy using the `breadth()` method of any iterable, or directly iterating over one, you can specify that the traversal should happen in a breadth-first order, i.e. all nodes of the same level in the hierarchy are processed before moving on to the next level.\n\nExample:\n```python\nroot = WeakTreeNode(some_object)\n\nroot.add_branch(one_fish).add_branch(two_fish)\n\nroot.add_branch(red_fish).add_branch(blue_fish)\n\nfor node in root.nodes().breadth():  # \u003c- Same as `for node in root:`\n    print(node)\n\n    # Expected order: Node(some_object), Node(one_fish), Node(red_fish), Node(two_fish), Node(blue_fish)\n\n```\n\n#### By Depth\n\nBy using the `depth()` method of any iterable, you can specify that the traversal should happen in a dpeth-first order, i.e. branches are followed to their furthest reaches before moving on to side branches.\n\nExample:\n```python\nroot = WeakTreeNode(some_object)\n\nroot.add_branch(one_fish).add_branch(two_fish)\n\nroot.add_branch(red_fish).add_branch(blue_fish)\n\nfor node in root.nodes().depth():\n    print(node)\n\n    # Expected order: Node(some_object), Node(one_fish), Node(two_fish), Node(red_fish), Node(blue_fish)\n\n```\n\n#### Towards the Root\n\nBy using the `towards_root()` method of any iterable, you can iterate towards the root of the tree.\n\nExample:\n```python\nroot = WeakTreeNode(some_object)\n\ntwo_fish_node = root.add_branch(one_fish).add_branch(two_fish)\n\nroot.add_branch(red_fish).add_branch(blue_fish)\n\nfor node in two_fish_node.nodes().towards_root():\n    print(node)\n\n    # Expected order: Node(two_fish), Node(one_fish), Node(some_object)\n\n```\n\n\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n## API Reference\n\n```python\nclass weaktree.WeakTreeNode(data: Any, trunk: WeakTreeNode | None, cleanup_mode: CleanupMode, callback: Callable | None)\n```\n\nThe base unit of a weak tree. Stores a weak reference to its data, and cleans itself up per the cleanup mode when that data expires. If a callback is provided, that will be called when the reference expires as well.\n\n```python\nmethod __init__(data: Any, trunk: WeakTreeNode | None, cleanup_mode: CleanupMode, callback: Callable | None) -\u003e None\n```\n\nCreates a new WeakTreeNode, storing the passed _data_, and as a branch of _trunk_, if trunk is provided. Optionally, cleanup mode can be specified to determine how the node will behave when the data expires. Additionally, the optional callback can allow further customization of cleanup behavior.\n\n```python\nproperty branches: set[WeakTreeNode]\n```\n\nRead-only.\n\nA set representing any branches that descend from the node. \n\n```python\nproperty cleanup_mode: CleanupMode\n```\n\nAn enum value that determines how the node will clenaup after itself when its data expires.\n\n```python\nproperty data: Any | None\n```\n\nThe stored data. When called, dereferences and returns either a strong reference to the data, or None if the data has expired.\n\n```python\nproperty trunk: WeakTreeNode | Node\n```\n\nThe previous node in the tree. If `None`, the node is considered a root.\n\n```python\nadd_branch(data: Any, cleanup_mode: CleanupMode, callback: Callable | None) -\u003e WeakTreeNode\n```\n\nCreates a new node as a branch of the calling node.\n\n```python\nbreadth() -\u003e Iterator[WeakTreeNode]\n```\n\nReturns an iterator that will traverse the tree by nodes, in a breadth-first pattern, starting at the calling node. Branches will be traversed in insertion order.\n\n\n```python\ndepth() -\u003e Iterator[WeakTreeNode]\n```\n\nReturns an iterator that will traverse the tree by nodes, in a depth-first pattern, starting at the calling node. Branches will be traversed in insertion order.\n\n```python\ntowards_root() -\u003e Iterator[WeakTreeNode]\n```\n\nReturns an iterator that will traverse the tree by nodes, up to the root, starting at the calling node.\n\n```python\nnodes() -\u003e NodeIterable\n```\n\nCreates an iterable that allows for traversing the tree by nodes. Has the same breadth(), depth(), and towards_root() methods as WeakTreeNode\n\n```python\nvalues() -\u003e ValueIterable\n```\n\nCreates an iterable that allows for traversing the tree by data values. Has the same breadth(), depth(), and towards_root() methods as WeakTreeNode\n\n```python\nitems() -\u003e ItemsIterable\n```\n\nCreates an iterable that allows for traversing the tree by node/value pairs. Has the same breadth(), depth(), and towards_root() methods as WeakTreeNode\n\n\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\n\u003c!-- ROADMAP --\u003e\n\u003c!-- ## Roadmap\n\n- [ ] (Eternal) Improve the renderer. Faster rendering means more renderables! --\u003e\n\n\u003c!--\n- [ ] Feature 2\n- [ ] Feature 3\n    - [ ] Nested Feature\n--\u003e\n\n\u003c!-- See the [open issues](https://github.com/BetterBuiltFool/weaktree/issues) for a full list of proposed features (and known issues). --\u003e\n\n\u003c!-- \u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e --\u003e\n\n\n\n\u003c!-- CONTRIBUTING --\u003e\n\u003c!--\n## Contributing\n\nContributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.\n\nIf you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag \"enhancement\".\nDon't forget to give the project a star! Thanks again!\n\n1. Fork the Project\n2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the Branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n### Top contributors:\n\n\u003ca href=\"https://github.com/BetterBuiltFool/weaktree/graphs/contributors\"\u003e\n  \u003cimg src=\"https://contrib.rocks/image?repo=BetterBuiltFool/weaktree\" alt=\"contrib.rocks image\" /\u003e\n\u003c/a\u003e\n--\u003e\n\n\n\n\u003c!-- LICENSE --\u003e\n## License\n\nDistributed under the MIT License. See `LICENSE.txt` for more information.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\n\u003c!-- CONTACT --\u003e\n## Contact\n\nBetter Built Fool - betterbuiltfool@gmail.com\n\nBluesky - [@betterbuiltfool.bsky.social](https://bsky.app/profile/betterbuiltfool.bsky.social)\n\u003c!--\n - [@twitter_handle](https://twitter.com/twitter_handle)\n--\u003e\n\nProject Link: [https://github.com/BetterBuiltFool/weaktree](https://github.com/BetterBuiltFool/weaktree)\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\n\u003c!-- ACKNOWLEDGMENTS --\u003e\n\u003c!--## Acknowledgments\n\n* []()\n* []()\n* []()\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n--\u003e\n\n\n\u003c!-- MARKDOWN LINKS \u0026 IMAGES --\u003e\n\u003c!-- https://www.markdownguide.org/basic-syntax/#reference-style-links --\u003e\n[contributors-shield]: https://img.shields.io/github/contributors/BetterBuiltFool/weaktree.svg?style=for-the-badge\n[contributors-url]: https://github.com/BetterBuiltFool/weaktree/graphs/contributors\n[forks-shield]: https://img.shields.io/github/forks/BetterBuiltFool/weaktree.svg?style=for-the-badge\n[forks-url]: https://github.com/BetterBuiltFool/weaktree/network/members\n[stars-shield]: https://img.shields.io/github/stars/BetterBuiltFool/weaktree.svg?style=for-the-badge\n[stars-url]: https://github.com/BetterBuiltFool/weaktree/stargazers\n[issues-shield]: https://img.shields.io/github/issues/BetterBuiltFool/weaktree.svg?style=for-the-badge\n[issues-url]: https://github.com/BetterBuiltFool/weaktree/issues\n[license-shield]: https://img.shields.io/github/license/BetterBuiltFool/weaktree.svg?style=for-the-badge\n[license-url]: https://github.com/BetterBuiltFool/weaktree/blob/main/LICENSE\n[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge\u0026logo=linkedin\u0026colorB=555\n[linkedin-url]: https://linkedin.com/in/linkedin_username\n[product-screenshot]: images/screenshot.png\n[Next.js]: https://img.shields.io/badge/next.js-000000?style=for-the-badge\u0026logo=nextdotjs\u0026logoColor=white\n[Next-url]: https://nextjs.org/\n[python.org]: https://img.shields.io/badge/python-3670A0?style=for-the-badge\u0026logo=python\u0026logoColor=ffdd54\n[python-url]: https://www.python.org/\n[React.js]: https://img.shields.io/badge/React-20232A?style=for-the-badge\u0026logo=react\u0026logoColor=61DAFB\n[React-url]: https://reactjs.org/\n[Vue.js]: https://img.shields.io/badge/Vue.js-35495E?style=for-the-badge\u0026logo=vuedotjs\u0026logoColor=4FC08D\n[Vue-url]: https://vuejs.org/\n[Angular.io]: https://img.shields.io/badge/Angular-DD0031?style=for-the-badge\u0026logo=angular\u0026logoColor=white\n[Angular-url]: https://angular.io/\n[Svelte.dev]: https://img.shields.io/badge/Svelte-4A4A55?style=for-the-badge\u0026logo=svelte\u0026logoColor=FF3E00\n[Svelte-url]: https://svelte.dev/\n[Laravel.com]: https://img.shields.io/badge/Laravel-FF2D20?style=for-the-badge\u0026logo=laravel\u0026logoColor=white\n[Laravel-url]: https://laravel.com\n[Bootstrap.com]: https://img.shields.io/badge/Bootstrap-563D7C?style=for-the-badge\u0026logo=bootstrap\u0026logoColor=white\n[Bootstrap-url]: https://getbootstrap.com\n[JQuery.com]: https://img.shields.io/badge/jQuery-0769AD?style=for-the-badge\u0026logo=jquery\u0026logoColor=white\n[JQuery-url]: https://jquery.com \n[pypi-url]: https://pypi.org/project/weaktree\n[pip-url]: https://pip.pypa.io/en/stable/","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbetterbuiltfool%2Fweaktree","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbetterbuiltfool%2Fweaktree","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbetterbuiltfool%2Fweaktree/lists"}