{"id":13738021,"url":"https://github.com/royerlab/arbol","last_synced_at":"2026-03-04T18:32:18.978Z","repository":{"id":43881576,"uuid":"318420024","full_name":"royerlab/arbol","owner":"royerlab","description":"arbol - Arborescent Printouts in Python","archived":false,"fork":false,"pushed_at":"2026-02-22T17:52:00.000Z","size":590,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-22T22:22:04.189Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/royerlab.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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-12-04T06:03:36.000Z","updated_at":"2026-02-22T17:52:04.000Z","dependencies_parsed_at":"2025-07-03T09:10:24.432Z","dependency_job_id":"6fe82552-93f5-4d9c-bd62-50aa542044fa","html_url":"https://github.com/royerlab/arbol","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/royerlab/arbol","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/royerlab%2Farbol","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/royerlab%2Farbol/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/royerlab%2Farbol/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/royerlab%2Farbol/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/royerlab","download_url":"https://codeload.github.com/royerlab/arbol/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/royerlab%2Farbol/sbom","scorecard":{"id":785846,"data":{"date":"2025-08-11","repo":{"name":"github.com/royerlab/arbol","commit":"1bfa85b3fdb93663d416e6819ef8145bf15fc4b4"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/28 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 4 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-23T06:04:41.855Z","repository_id":43881576,"created_at":"2025-08-23T06:04:41.855Z","updated_at":"2025-08-23T06:04:41.855Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30089346,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T18:31:08.343Z","status":"ssl_error","status_checked_at":"2026-03-04T18:31:07.708Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":"2024-08-03T03:02:09.101Z","updated_at":"2026-03-04T18:32:18.939Z","avatar_url":"https://github.com/royerlab.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# arbol | Python Package for Arborescent Printouts in Python\n![s](arbol.png) \nDo you have a script, a command line tool, or some workflow in Python that has lots of 'print' statements,\nand you can't make sense of it once it adds up to hundreds of lines on the console? Sounds familiar?  \n_arbol_ organises your stdout prints in a hierarchy that follows the structure of your code. Use a simple \ncontext manager to define the hierarchy and the 'aprint' command instead of print, and voila.\nFinally, when the optional dependencies are installed, the printed tree and text are colored with an \nexquisitely crafted combination of colors, making it even more visually appealing.  \n\nIf you are wondering, 'arbol' means 'tree' in spanish.  \n\nWhy not use a more traditional Python logging? We have made the choice of sticking to a plain and simple \nscheme that matches the usage of 'print' statements.\n\n## Features\n\nYou can use 'aprint' replacement for the built-in 'print'.\nYou create a new 'node' in the tree with the 'asection' contact manager. Moreover, _arbol_ measures the elapsed time for each node of the tree and displays that conveniently.\nYou have several configuration flags in the Arbol class to tune things. If yo want to capture print statements originating from 3rd party code,\nyou can use the 'acapture' context manager to capture stdout (and stderr) -- tis is a bit experimental and is best used sparingly.\nThe best documentation is simply the demo below...  \n\n## Installation\n\nInstall with pip:\n\n```sh\npip install arbol\n```\n\n## Optional dependencies\n\nIf you want colors, install the [ansicolors](https://pypi.org/project/ansicolors/) package:\n\n```sh\npip install ansicolors\n```\n\nTo make sure that you get the colors on all operating systems (particularly Windows), install the [colorama](https://pypi.org/project/colorama/)\npackage:\n\n```sh\npip install colorama\n```\n\nNote: both colorama and ansicolors are optional -- _arbol_ will work fine without it installed.\n\nTo run the tests you will need Pytest:\n\n```sh\npip install pytest\n```\n\n\n## Example\nHere is a simple and self-explanatory example:\n```python\n\nfrom arbol import Arbol, aprint, section, asection, acapture\n\nimport arbol\n\n# for colors, install the ansicolors package: 'pip install ansicolors',\n# and for windows install the colorama package: 'pip install colorama'\n\n# You can limit the tree depth:\nArbol.max_depth = 4\n\n# use aprint (=arbol print) instead of the standard print\naprint('Test')\n\n# You can decorate functions:\n@section('function')\ndef fun(x):\n    if x \u003e= 0:\n        with asection('recursive call to f'):\n            aprint(f\"f(x)+1={fun(x - 1)}\")\n\n# The context manager let's you go down one level in the tree\nwith asection('a section'):\n    aprint('a line')\n    aprint('another line')\n    aprint('we are done \\n or are we? \\n someone gotta check!')\n\n    with asection('a subsection'):\n        aprint('another line')\n        aprint('we are done')\n\n    # works through function calls and the like...\n    fun(2)\n\n    # You can capture stdout if you want, usefull when a 3rd party library has printouts that you want to capture...\n    with acapture():\n        print(\"No escape is possible\")\n        aprint(\"Even this works...\\n\")\n        # Don't push it.. sections will not work right now...\n\n    # You can deactivate the elapsed time measurement and printing:\n    Arbol.elapsed_time = False\n    fun(100)\n\naprint('demo is finished...')\n\n# You can also turn off all output with one switch:\nArbol.enable_output = False\naprint('you will not see that')\n\n\n```\n\nAnd this is how it looks like:\n\n![example](example.png)\n\n## Roadmap\nSome ideas we might consider from serious to highly speculative:\n- More color styles to choose from\n- Intercept stdout from C code so that printouts from libraries called from python are formatted too, unclear is that's possible.\n- Generate tree automatically by inspecting stack?\n- Interoperability with logging package? \n- How to handle multiple threads/processes? Right now, the printouts get interleaved stochastically which is messy and incomprehensible. One idea is to capture all outputs from each thread, hold onto these outputs until the thread is done (perhaps via a dedicated 'holding' context manager), and ouput it all in order and separately. Probably doable. \n\n## Contributions\n\nPull requests highly welcome! \n\n## Authors\n\nLoic A. Royer (@loicaroyer)\nAhmet Can Solak (@_ahmetcansolak)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froyerlab%2Farbol","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froyerlab%2Farbol","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froyerlab%2Farbol/lists"}