{"id":37085707,"url":"https://github.com/scottvr/phart","last_synced_at":"2026-01-14T10:32:40.671Z","repository":{"id":265029385,"uuid":"894905240","full_name":"scottvr/phart","owner":"scottvr","description":"phart: Python Hierarchical ASCII Representation Tool -  A Pure Python console/text graph visualization, no external dependencies*  * except NetworkX, which should be mentioned prominently. but phart will not require you to stand up a webserver to run PHP and install Perl and some libraries just to render a Graph in 7-bit text (or UTF-8 or Unicode)","archived":false,"fork":false,"pushed_at":"2025-02-25T03:24:11.000Z","size":710,"stargazers_count":13,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-07T02:48:06.733Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://blehg.paperclipmaximizer.ai/phart/","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/scottvr.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}},"created_at":"2024-11-27T08:03:25.000Z","updated_at":"2025-03-09T13:36:54.000Z","dependencies_parsed_at":"2024-11-27T09:23:37.330Z","dependency_job_id":"3aeb4c78-aace-420c-bedc-d7a3094c90f7","html_url":"https://github.com/scottvr/phart","commit_stats":null,"previous_names":["scottvr/graphscii","scottvr/phart"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/scottvr/phart","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottvr%2Fphart","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottvr%2Fphart/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottvr%2Fphart/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottvr%2Fphart/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scottvr","download_url":"https://codeload.github.com/scottvr/phart/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottvr%2Fphart/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28417489,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:25:19.714Z","status":"ssl_error","status_checked_at":"2026-01-14T10:22:49.371Z","response_time":107,"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":"2026-01-14T10:32:40.067Z","updated_at":"2026-01-14T10:32:40.666Z","avatar_url":"https://github.com/scottvr.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# phart\n\n**PHART:** The Python Hierarchical ASCII Representation Tool - A Pure Python graph visualization in ASCII, no external dependencies\\*\n\n\\* except NetworkX, which should be mentioned prominently. but **phart** will **not** require you to stand up a webserver to run PHP and install Perl and some libraries just to render a Graph in 7-bit text (or UTF-8 or Unicode) from Python.\n\n## Features\n\n- Pure Python implementation\n- Render using 7-bit ASCII or unicode characters\n- No external dependencies (except NetworkX)\n- Multiple node styles (square, round, diamond, custom)\n- Customizable edge characters\n- Support for directed and undirected graphs\n- Handles cycles and complex layouts\n- Bidirectional edge support\n- Orthogonal (yet correct, though perhaps unexpected) Triad Layout\n  \n## Examples\n\n\u003cdetails\u003e\n\n\u003csummary\u003eExample output PHARTs [click triangle/arrow to expand/collapse]\u003c/summary\u003e\n\n## PHART Graph Visualization Examples\n\n=================================\n\n### In preparation for a 1.0 PyPi release\n\nI was doing some last-minute testing and came across this, from the networkx gallery:\n\nhttps://networkx.org/documentation/latest/auto_examples/drawing/plot_chess_masters.html#sphx-glr-auto-examples-drawing-plot-chess-masters-py\n\nThe code there creates a graph from some data pulled from a database of Chess masters tournaments and such at this site:\n\nhttps://chessproblem.my-free-games.com/chess/games/Download-PGN.php\n\nAnd plots it with matplotlib. It looked pretty complex so I thought as a lark I would see how difficult it would be to get phart to render the graph. The matplot can be seen here:\n\n![screen capture of graph plot](https://github.com/scottvr/phart/blob/67bd3d02b6ad9cc4a8a09fe6fc2920a6712f5c7a/examples/WCC-plt-Capture.png)\n\nSo, I added the following to the code at the networkx gallery page linked above:\n\n```\nfrom phart import ASCIIRenderer, NodeStyle\n\n.. existing code remains here ...\n\n... then directly below the existing lines to create the nx graph:\n# make new undirected graph H without multi-edges\nH = nx.Graph(G)\n... I added this:\nrenderer=ASCIIRenderer(H)\nrenderer.write_to_file(\"wcc.txt\")\n```\n\nand ran the code. Immediately this was written to wcc.txt:\n\n```\n                               ---------------------------------[Botvinnik, Mikhail M]---------------------------------\n                               |               |                           |                 |                        |\n            v                  |               |                    v      |                 |                        |                     v\n  [Bronstein, David I]----[Euwe, Max]----[Keres, Paul]----[Petrosian, Tigran V]----[Reshevsky, Samuel H]----[Smyslov, Vassily V]----[Tal, Mikhail N]\n                               ^                               |    |\n                                                               |    |                   v\n                                                    [Alekhine, Alexander A]----[Spassky, Boris V]\n                                                               |           |            |\n                                                  v            |           |            |           v\n                                        [Bogoljubow, Efim D]----[Capablanca, Jose Raul] ---[Fischer, Robert J]\n                                                                          |^\n                                                                          |\n                                                                  [Lasker, Emanuel]--------------\n                                                                          |                     |\n                            v                      v                      v                     |                       v\n                   [Janowski, Dawid M]----[Marshall, Frank J]----[Schlechter, Carl]----[Steinitz, Wilhelm]----[Tarrasch, Siegbert]\n                                                                                                |  |\n                                                 v                        v                     |  |\n                                       [Chigorin, Mikhail I]----[Gunsberg, Isidor A]----[Zukertort, Johannes H]\n\n\n                                            [Karpov, Anatoly]----[Kasparov, Gary]----[Korchnoi, Viktor L]\n```\n\nNo fuss. No muss. Just phart.\n\n### Software Dependency Example:\n\n```\n            [main.py]\n                |\n         v      |       v\n    [config.py]----[utils.py]\n         |              |\n         v              | v\n  [constants.py]----[helpers.py]\n```\n\n### Organizational Hierarchy Example:\n\n```\n                                       [CEO]\n                                         |\n                                v        v        v\n                              [CFO]----[COO]----[CTO]\n                                |        |        |\n        v              v        |      v |        |       v                v\n  [Controller]----[Dev Lead]----[Marketing Dir]----[Research Lead]----[Sales Dir]\n```\n\n### Network Topology Example:\n\n```\n                     [Router1]\n                         |\n                   v     |      v\n               [Switch1]----[Switch2]\n                   |            |\n      v            v            |            v\n  [Server1]----[Server2]    [Server3]----[Server4]\n```\n\n### Workflow Example:\n\n```\n        [Start]\n           |\n           v\n        [Input]\n           |\n           |v\n       [Validate]\n            |\n           v|\n     --[Process]\n     |     ^\n     |     v\n     |  [Check]\n     |     |\n     |     |     v\n  [Error]----[Success]\n                 |\n            v    |\n        [Output]--\n            |\n           v|\n         [End]\n```\n\n### DOT Import Example:\n\n```\n     [A]\n      |\n   v  |   v\n  [B]----[D]\n   |      |\n   |  v   |\n   --[C]---\n      |\n      v\n     [E]\n```\n\n## Custom Styling Example:\n\nDifferent node styles for the same graph:\n\n### Using MINIMAL style:\n\n```\n         0\n         |\n       v |  v\n       1----2\n       |    |\n  v    v    |    v\n  3----4    5----6\n```\n\n### Using SQUARE style:\n\n```\n            [0]\n             |\n          v  |   v\n         [1]----[2]\n          |      |\n   v      v      |      v\n  [3]----[4]    [5]----[6]\n```\n\n### Using ROUND style:\n\n```\n            (0)\n             |\n          v  |   v\n         (1)----(2)\n          |      |\n   v      v      |      v\n  (3)----(4)    (5)----(6)\n```\n\n### Using DIAMOND style:\n\n```\n            \u003c0\u003e\n             |\n          v  |   v\n         \u003c1\u003e----\u003c2\u003e\n          |      |\n   v      v      |      v\n  \u003c3\u003e----\u003c4\u003e    \u003c5\u003e----\u003c6\u003e\n```\n\n\u003c/details\u003e\n\n## Why PHART?\n\nBecause it demanded to come out. OK, sorry... Actually it had a few other names early on, but when it came time to upload to PyPi, we discovered the early names we chose were already taken so we had to choose a new name. We wanted to mash up the relevant terms (\"graph\", \"ascii\", \"art\", \"chart\", and such) and bonus if the new name is a fitting acronym.\n\nIn the case of PHART, the acronym made from the first letters of the obvious first words to come to mind was discovered to spell PHART after the non abbreviated words were suggested. Fortuitous; so it had to be. Also, as I am beginning to update the usage instructions and the examples and their output in the README to more accurately reflect current capabilities, it occurs to me that the name may not be as fitting anymore. At first release PHART only handled DAGs and fairly strictly rendered a heirarchical layout. \n\nAs it's capabilities have increased (by user request if you can believe that!) faster than my knowledge of Graphs and the layout thereof, and my lack of deep understanding of exactly what NetworkX's focus and strengths are (to be fair, their dev lists and Roadmap would seem to align quite well with me not fully understanding their focus and direction, and I mean no disrespect; it's way beyond me.) Anyway, as such at times I struggle with having to remind myself \"that information is already known - to the graph - you don't need to calculate or keep track of that, similarly with certain layout decisions that really don't need to be pondered by PHART at all I have spent too many hours working on. \n\nSo it might be more properly named something that indicates that it sometimes adheres mostly to a Hierarchical Layout strategy, but other times it might be more accurately branded an Orthogonal Layout. Either way, I'm not sure I knew either of those were terms for some known thing at the time I started implementing. Nevertheless, perhaps its name needs to expand along with its function. Something incorporating Orthogonal Layout. Hmm.. \"**OL-PHART**\" perhaps. Maybe it has become **B**oundary **I**nvariant **G**eodesic **O**rthogonal **L**ayout **PHART** - that is...\n\n**BIGOL-PHART**\n\nRegardless, you may pronounce it the obvious monosyllabic way, or as \"eff art\", or perhaps \"pee heart\", or any way that you like, so long as the audience you are speaking it to knows it is PHART you are referring to.\n\n## Really, why?\n\nThe mention of not being Perl or a PHP webapp may appear to be throwing shade at the existing solutions, but it is meant in a good-hearted way. Wrapping the OG Graph::Easy is a straightforeard way to go about it, and a web interface to the same is a project I might create as well, but Perl being installed is not the sure ubiquitous thing it once was, and spinning up a Docker container in order to add ascii art graph output to a python tool seemed a bit excessive.\n\nAdditionally, I'm not sure how I didn't find pydot2ascii - which is native python - when I first looked for a solution, but even if I had seen it I may not have realized that I could have exported my NX DAG to DOT, and then used pydot2ascii to go from DOT to ascii art.\n\nSo now we have PHART, and the ability to render a NX digraph in ASCII/Unicode, read a DOT file, read GraphML, and a few other things in a well-tested Python module published to PyPi. I hope you find it useful.\n\n## Installation\n\nrequires Python \u003e= 3.10 and NetworkX \u003e= 3.3\n\n```bash\npip install phart\n```\n\n## The CLI\n\nThese docs are pretty out of date now, which I will try to remedy soon.\nIn the mean time, I should mention that the primary focus lately has been\nuse from the CLI command `phart` which is installed when you install via pip.\nThis repor is well ahead of the release in PyPi as I work on some specific\ngraphlet features for a user. I will update the docs to match when the package is released.\nBut to fill in some of the info garp here is the CLI usage info, which should be\nself-explanatory to many of you.\n\n```bash\n└─$ phart --help\nusage: phart [-h] [--output OUTPUT] [--style {minimal,square,round,diamond,custom}]\n             [--node-spacing NODE_SPACING] [--layer-spacing LAYER_SPACING] [--charset {ascii,unicode}]\n             [--ascii] [--function FUNCTION]\n             input\n\nPHART: Python Hierarchical ASCII Rendering Tool\n\npositional arguments:\n  input                 Input file (.dot, .graphml, or .py format)\n\noptions:\n  -h, --help            show this help message and exit\n  --output OUTPUT, -o OUTPUT\n                        Output file (if not specified, prints to stdout)\n  --style {minimal,square,round,diamond,custom}\n                        Node style (default: square)\n  --node-spacing NODE_SPACING\n                        Horizontal space between nodes (default: 4)\n  --layer-spacing LAYER_SPACING\n                        Vertical space between layers (default: 2)\n  --charset {ascii,unicode}\n                        Character set to use for rendering (default: unicode)\n  --ascii               Force ASCII output (deprecated, use --charset ascii instead)\n  --function FUNCTION, -f FUNCTION\n                        Function to call in Python file (default: main)\n```\n\n## Quick Start\n\n```python\nimport networkx as nx\nfrom phart import ASCIIRenderer\n\n# Create a simple graph\nG = nx.DiGraph()\nG.add_edges_from([(\"A\", \"B\"), (\"A\", \"C\"), (\"B\", \"D\")])\n\n# Render it in ASCII\nrenderer = ASCIIRenderer(G)\nprint(renderer.render())\n\n     [A]\n      │\n   v  │   v\n  [B]────[C]\n   │\n   │  v\n   ──[D]\n```\n\nThe renderer shows edge direction using arrows:\n\n- v : downward flow\n- ^ : upward flow\n- \u0026gt; or \u003c : horizontal flow\n\nThese directional indicators are particularly useful for:\n\n- Dependency graphs\n- Workflow diagrams\n- Process flows\n- Any directed relationships\n\n# Extras\n\n## Character Sets\n\nPHART supports multiple character sets for rendering:\n\n- `--charset unicode` (default): Uses Unicode box drawing characters and arrows for\n  cleaner visualization\n- `--charset ascii`: Uses only 7-bit ASCII characters, ensuring maximum compatibility\n  with all terminals\n\nExample:\n\n```bash\n# Using Unicode (default)\nphart graph.dot\n# ┌─A─┐\n# │   │\n# └─B─┘\n\n# Using ASCII only\nphart --charset ascii graph.dot\n# +-A-+\n# |   |\n# +-B-+\n```\n\n## File Format Support\n\n### DOT Files\n\n- DOT file support\n- requires pydot\n\n```bash\npip install phart[extras]\n```\n\nor using requirements file\n\n```bash\npip install -r requirements\\extra.txt\n```\n\n### Example\n\n    \u003e\u003e\u003e dot = '''\n    ... digraph {\n    ...     A -\u003e B\n    ...     B -\u003e C\n    ... }\n    ... '''\n    \u003e\u003e\u003e renderer = ASCIIRenderer.from_dot(dot)\n    \u003e\u003e\u003e print(renderer.render())\n    A\n    |\n    B\n    |\n    C\n    \u003e\u003e\u003e\n\n### Note on DOT format support:\n\n---\n\nPHART uses pydot for DOT format support. When processing DOT strings containing\nmultiple graph definitions, only the first graph will be rendered. For more\ncomplex DOT processing needs, you can convert your graphs using NetworkX's\nvarious graph reading utilities before passing them to PHART.\n\n### GraphML Files\n\nPHART supports reading GraphML files:\n\n```python\nrenderer = ASCIIRenderer.from_graphml(\"graph.graphml\")\nprint(renderer.render())\n```\n\nor, of course just\n```bash\nphart graph.graphml \n```\n## Python Files\n\nPHART can directly execute Python files that create and render graphs. When given a Python file, PHART will:\n\n1. First try to execute the specified function (if `--function` is provided)\n2. Otherwise, try to execute a `main()` function if one exists\n3. Finally, execute code in the `if __name__ == \"__main__\":` block\n\nExample Python file:\n\n```python\nimport networkx as nx\nfrom phart import ASCIIRenderer\n\ndef demonstrate_graph():\n    # Create a simple directed graph\n    G = nx.DiGraph()\n    G.add_edges_from([(\"A\", \"B\"), (\"B\", \"C\")])\n\n    # Create renderer and display the graph\n    renderer = ASCIIRenderer(G)\n    print(renderer.render())\n\nif __name__ == \"__main__\":\n    demonstrate_graph()\n```\n\nYou can execute this file in several ways:\n\n```bash\n# Execute main() or __main__ block (default behavior)\nphart graph.py\n\n# Execute a specific function\nphart graph.py --function demonstrate_graph\n\n# Use specific rendering options\nphart graph.py --charset ascii --style round\n```\n\n### Option Handling\n\nWhen executing Python files, PHART intelligently merges command-line options with any\noptions specified in your code:\n\n- Options set in your Python code (like custom_decorators or specific node styles) are preserved\n- Command-line options will override general settings (like --charset or --style)\n- Custom settings (like custom_decorators) are never overridden by command-line defaults\n\nThis means you can set specific options in your code while still using command-line\noptions to adjust general rendering settings.\n\n## License\n\nMIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscottvr%2Fphart","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscottvr%2Fphart","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscottvr%2Fphart/lists"}