{"id":46650014,"url":"https://github.com/tmarktaylor/monotable","last_synced_at":"2026-03-08T06:04:51.860Z","repository":{"id":57443052,"uuid":"85603653","full_name":"tmarktaylor/monotable","owner":"tmarktaylor","description":"ASCII table with per column format specs, multi-line content, plug-in format functions, column width control.","archived":false,"fork":false,"pushed_at":"2024-09-14T15:14:23.000Z","size":476,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-09-28T15:04:50.493Z","etag":null,"topics":["ascii-table","dataclass"],"latest_commit_sha":null,"homepage":"https://github.com/tmarktaylor/monotable/blob/v3.2.0/README.md","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tmarktaylor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"contributing.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-20T17:03:11.000Z","updated_at":"2024-09-14T15:57:58.000Z","dependencies_parsed_at":"2022-09-26T17:21:30.305Z","dependency_job_id":null,"html_url":"https://github.com/tmarktaylor/monotable","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/tmarktaylor/monotable","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmarktaylor%2Fmonotable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmarktaylor%2Fmonotable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmarktaylor%2Fmonotable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmarktaylor%2Fmonotable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tmarktaylor","download_url":"https://codeload.github.com/tmarktaylor/monotable/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmarktaylor%2Fmonotable/sbom","scorecard":{"id":889648,"data":{"date":"2025-08-11","repo":{"name":"github.com/tmarktaylor/monotable","commit":"078f9a3ee273a089b6adf7c6abf9a9e25b42ce30"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.8,"checks":[{"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":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","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":"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build.yml:1","Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/ci_readme.yml:1","Warn: no topLevel permission defined: .github/workflows/publish.yml:1","Warn: no topLevel permission defined: .github/workflows/wheel.yml:1","Info: no jobLevel write permissions found"],"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":"Code-Review","score":0,"reason":"Found 0/1 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":"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":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:79: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:82: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:99: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:112: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:113: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:119: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:148: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:150: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:167: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci_readme.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci_readme.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci_readme.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci_readme.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci_readme.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci_readme.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci_readme.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci_readme.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci_readme.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci_readme.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci_readme.yml:54: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/ci_readme.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:44: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/publish.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/publish.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish.yml:56: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/wheel.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/tmarktaylor/monotable/wheel.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/build.yml:18","Warn: pipCommand not pinned by hash: .github/workflows/build.yml:19","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:67","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:68","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:69","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:87","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:88","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:89","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:124","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:125","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:126","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:156","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:157","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:158","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:27","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:28","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:29","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:37","Warn: pipCommand not pinned by hash: .github/workflows/ci_readme.yml:27","Warn: pipCommand not pinned by hash: .github/workflows/ci_readme.yml:28","Warn: pipCommand not pinned by hash: .github/workflows/ci_readme.yml:52","Warn: pipCommand not pinned by hash: .github/workflows/ci_readme.yml:53","Warn: pipCommand not pinned by hash: .github/workflows/publish.yml:25","Warn: pipCommand not pinned by hash: .github/workflows/wheel.yml:20","Warn: pipCommand not pinned by hash: .github/workflows/wheel.yml:21","Info:   0 out of  27 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned","Info:   0 out of  25 pipCommand dependencies pinned"],"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":"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":"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":"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: 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":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/publish.yml:36"],"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":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"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":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 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-24T11:17:57.923Z","repository_id":57443052,"created_at":"2025-08-24T11:17:57.923Z","updated_at":"2025-08-24T11:17:57.923Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30246884,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T05:41:50.788Z","status":"ssl_error","status_checked_at":"2026-03-08T05:41:39.075Z","response_time":56,"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":["ascii-table","dataclass"],"created_at":"2026-03-08T06:04:51.391Z","updated_at":"2026-03-08T06:04:51.851Z","avatar_url":"https://github.com/tmarktaylor.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# monotable\n\nASCII table with per column format specs, multi-line content,\nformatting directives, column width control.\n\nDataclass to ASCII table printer.\n\n## default branch status\n\n[![](https://img.shields.io/pypi/l/monotable.svg)](http://www.apache.org/licenses/LICENSE-2.0)\n[![](https://img.shields.io/pypi/v/monotable.svg)](https://pypi.python.org/pypi/monotable)\n[![](https://img.shields.io/pypi/pyversions/monotable.svg)](https://pypi.python.org/pypi/monotable)\n\n[![CI Test](https://github.com/tmarktaylor/monotable/actions/workflows/ci.yml/badge.svg)](https://github.com/tmarktaylor/monotable/actions/workflows/ci.yml)\n[![readthedocs](https://readthedocs.org/projects/monotable/badge/?version=latest)](https://monotable.readthedocs.io/en/latest/?badge=latest)\n[![codecov](https://codecov.io/gh/tmarktaylor/monotable/branch/master/graph/badge.svg?token=qanSaWfGAQ)](https://codecov.io/gh/tmarktaylor/monotable)\n\n[Docs](https://monotable.readthedocs.io/en/latest/) |\n[Repos](https://github.com/tmarktaylor/monotable) |\n[Codecov](https://codecov.io/gh/tmarktaylor/monotable?branch=master) |\n[License](https://github.com/tmarktaylor/monotable/blob/master/LICENSE)\n\n## Sample usage\n\n```python\nfrom monotable import mono\n\nheadings = [\"purchased\\nparrot\\nheart rate\", \"life\\nstate\"]\n\n# \u003e is needed to right align None cell since it auto-aligns to left.\n# monotable uses empty string to format the second column.\nformats = [\"\u003e(none=rest).0f\"]\ncells = [\n    [0, \"demised\"],\n    [0.0, \"passed on\"],\n    [None, \"is no more\"],\n    [-1],\n    [0, \"ceased to be\"],\n]\n\nprint(\n    mono(\n        headings,\n        formats,\n        cells,\n        title=\"Complaint\\n(registered)\",\n        # top guideline is equals, heading is period, bottom is omitted.\n        guideline_chars=\"=. \",\n    )\n)\n```\n\nsample output:\n\n```expected-output\n       Complaint\n      (registered)\n========================\n purchased\n    parrot  life\nheart rate  state\n........................\n         0  demised\n         0  passed on\n      rest  is no more\n        -1\n         0  ceased to be\n```\n\n## Dataclass to ASCII Table printer\n\n```python\nfrom dataclasses import dataclass, field\nfrom enum import auto, Enum\nfrom monotable import dataclass_print\nfrom monotable import dataclass_format\nfrom monotable import stow\n```\n\n### Print a dataclass instance\n\nPrint a dataclass as an ASCII table. The field names are left\njustified in the left column. The values are right justified\nin the right column.\n\n```python\n@dataclass\nclass CurrentConditions:\n    temperature: float\n    humidity: float\n    heat_index: int\n\nweather_data = CurrentConditions(80.0, 0.71, 83)\ndataclass_print(weather_data)\n```\n\n```expected-output\nCurrentConditions\n-----------------\ntemperature  80.0\nhumidity     0.71\nheat_index     83\n-----------------\n```\n\n### Title\n\nThe table title defaults to the class name. The string passed\nto the \"title\" keyword is prepended to the class name.\n\n```python\ndataclass_print(weather_data, title=\"Airport\")\n```\n\n```expected-output\nAirport : CurrentConditions\n-----------------\ntemperature  80.0\nhumidity     0.71\nheat_index     83\n-----------------\n```\n\n### Format and print later\n\nCall dataclass_format() to print or log later.\n\n```python\ntext = dataclass_format(weather_data, title=\"Airport\")\nprint(text)\n```\n\n```expected-output\nAirport : CurrentConditions\n-----------------\ntemperature  80.0\nhumidity     0.71\nheat_index     83\n-----------------\n```\n\n### Add a format spec to a dataclass field\n\nSpecify formatting for a data class field as shown for\nthe field() call in place of the default value for the\nhumidity field below.\n\nThe function stow() assigns the dict {\"spec\": \".0%\"} to\nthe field's metadata dict as the value for the key\n\"monotable\".\nThe code internally applies this f-string: f\"{value:{spec}}\"\nto format the value.\n\n```python\n@dataclass\nclass SpecCurrentConditions:\n    temperature: float\n    humidity: float = field(metadata=stow(spec=\".0%\"))\n    heat_index: int\n\nweather_data = SpecCurrentConditions(80.0, 0.71, 83)\ndataclass_print(weather_data)\n```\n\n```expected-output\nSpecCurrentConditions\n-----------------\ntemperature  80.0\nhumidity      71%\nheat_index     83\n-----------------\n```\n\n### Add a format function to a dataclass field\n\nSpecify a format function to do the formatting for a field.\n\nSet the 'spec' key to a callable.\nThe function takes the field value as the parameter and returns a string.\nThe string is printed in the table. Note that just the enumeration\nname \"E\" is printed instead of \"Direction.E\".\n\n```python\nclass Direction(Enum):\n    N = auto()\n    E = auto()\n    S = auto()\n    W = auto()\n\n\n@dataclass\nclass Wind:\n    speed: int\n    direction: Direction = field(metadata=stow(spec=lambda x: x.name))\n\nwind_data = Wind(speed=11,direction=Direction.E)\ndataclass_print(wind_data)\n```\n\n```expected-output\n     Wind\n-------------\nspeed      11\ndirection   E\n-------------\n```\n\n### Add text to embellish a field name\n\nSet the 'help' key to add text immediately after the field name.\nThis is printed in the table left column:\n- dataclass field name\n- 2 spaces\n- 'help' key value.\n\n```python\n@dataclass\nclass MoreConditions:\n    visibility: float = field(metadata=stow(help=\"(mi)\",spec=\".2f\"))\n    dewpoint: int = field(metadata=stow(help=\"(degF)\"))\n\nmore_data = MoreConditions(visibility=10.00,dewpoint=71)\ndataclass_print(more_data)\n```\n\n```expected-output\n     MoreConditions\n-----------------------\nvisibility  (mi)  10.00\ndewpoint  (degF)     71\n-----------------------\n```\n\n### When a dataclass field value is also dataclass\n\nAn additional ASCII table is printed for each nested dataclass.\nThe table is below and indented two spaces for each level of nesting.\n\n```python\n@dataclass\nclass MoreCurrentConditions:\n    temperature: float\n    humidity: float\n    heat_index: int\n    wind: Wind = field(metadata=stow(help=\"(2pm)\"))\n\nmore_weather_data = MoreCurrentConditions(\n    80.0, 0.71, 83, Wind(11, Direction.E)\n    )\ndataclass_print(more_weather_data)\n```\n\nThe class name is printed in place of the value. The value of\nthe wind field is printed in a second table below the first\nand indented two spaces.\n\n```expected-output\nMoreCurrentConditions\n-----------------\ntemperature  80.0\nhumidity     0.71\nheat_index     83\nwind  (2pm)  Wind\n-----------------\n\n  MoreCurrentConditions.wind  (2pm) : Wind\n  -------------\n  speed      11\n  direction   E\n  -------------\n```\n\n#### Omit printing a nested dataclass\n\nTo prevent levels of nested dataclasses from printing pass\nkeyword parameter max_depth. 1 means just print the top\nlevel of dataclass. Note that only the classname of\nthe wind field value is printed.\n\n```python\ndataclass_print(more_weather_data, max_depth=1)\n```\n\n```expected-output\nMoreCurrentConditions\n-----------------\ntemperature  80.0\nhumidity     0.71\nheat_index     83\nwind  (2pm)  Wind\n-----------------\n```\n\n\n#### Print a bordered ASCII table\n\ndataclass_print() passes extra keyword arguments to monotable.mono().\nSee monotable.mono()'s documentation. Some examples are below.\n\n```python\ndataclass_print(more_weather_data, max_depth=1, bordered=True)\n```\n\n```expected-output\nMoreCurrentConditions\n+-------------+------+\n| temperature | 80.0 |\n+-------------+------+\n| humidity    | 0.71 |\n+-------------+------+\n| heat_index  |   83 |\n+-------------+------+\n| wind  (2pm) | Wind |\n+-------------+------+\n```\n\n#### Print ASCII table with indent\n\n```python\ndataclass_print(more_weather_data, max_depth=1, indent=\"....\")\n```\n\n```expected-output\n....MoreCurrentConditions\n....-----------------\n....temperature  80.0\n....humidity     0.71\n....heat_index     83\n....wind  (2pm)  Wind\n....-----------------\n```\n\n#### Change the column alignment\n\n```python\ndataclass_print(more_weather_data, max_depth=1, formats=(\"\u003e\", \"\u003c\"))\n```\n\n```expected-output\nMoreCurrentConditions\n-----------------\ntemperature  80.0\n   humidity  0.71\n heat_index  83\nwind  (2pm)  Wind\n-----------------\n```\n\n#### Print a nested dataclass that has a callable spec\n\nFor a dataclass field value, set the monotable field metadata\n\"spec\" key to a function so that the value is printed in the top\nlevel table rather than below as a separate table.\n\nNote- This example is coded in Python REPL style so it can be tested\nby the PYPI project phmutest using --replmode.\n\n```python\n\u003e\u003e\u003e from dataclasses import dataclass, field\n\u003e\u003e\u003e from enum import auto, Enum\n\u003e\u003e\u003e\n\u003e\u003e\u003e from monotable import dataclass_print\n\u003e\u003e\u003e from monotable import stow\n\u003e\u003e\u003e\n\u003e\u003e\u003e class Direction(Enum):\n...     N = auto()\n...     E = auto()\n...     S = auto()\n...     W = auto()\n\u003e\u003e\u003e\n\u003e\u003e\u003e @dataclass\n... class Wind:\n...     speed: int\n...     direction: Direction = field(metadata=stow(spec=lambda x: x.name))\n\u003e\u003e\u003e\n\u003e\u003e\u003e @dataclass\n... class WindInline:\n...     temperature: float\n...     humidity: float\n...     heat_index: int\n...     wind: Wind = field(metadata=stow(spec=str))\n\n\u003e\u003e\u003e wind = Wind(11, Direction.E)\n\u003e\u003e\u003e wind_inline = WindInline(80.0, 0.71, 83, wind)\n\u003e\u003e\u003e dataclass_print(wind_inline)\n                       WindInline\n-------------------------------------------------------\ntemperature                                        80.0\nhumidity                                           0.71\nheat_index                                           83\nwind         Wind(speed=11, direction=\u003cDirection.E: 2\u003e)\n-------------------------------------------------------\n```\n\n#### Left align the title\n\nNote \"\u003c\" at the start of title= specifies left alignment.\nmonotable detects alignment from the first character of the title.\n\n```python\n\u003e\u003e\u003e dataclass_print(wind_inline, title=\"\u003cLeft Aligned Title\")\nLeft Aligned Title : WindInline\n-------------------------------------------------------\ntemperature                                        80.0\nhumidity                                           0.71\nheat_index                                           83\nwind         Wind(speed=11, direction=\u003cDirection.E: 2\u003e)\n-------------------------------------------------------\n```\n\n#### Recipe to do dataclass_print as a mixin class.\n\n```python\nfrom typing import Any, Tuple\n\nclass DCPrint:\n    \"\"\"Mixin class for dataclass to add member function dcprint().\"\"\"\n\n    # This should be the same signature as dataclass_print()\n    # where dataclass_instance is replaced by self.\n    def dcprint(\n        self,\n        *,\n        # note- These 2 keyword args are monotable positional args.\n        formats: Tuple[str, str] = (\"\", \"\u003e\"),\n        title: str = \"\",  # monotable title prefix\n        **monotable_kwargs: Any,  # keyword args passed to monotable.mono().\n    ) -\u003e None:\n\n        dataclass_print(\n            self,\n            formats=formats,\n            title=title,\n            **monotable_kwargs,\n        )\n```\n\nAdd DCPrint as a base class to the dataclass definition.\n\n```python\n@dataclass\nclass Temperatures(DCPrint):\n    high: int\n    low: int\n\ntemps = Temperatures(high=77, low=60)\ntemps.dcprint(title=\"High/Low Temperature\")\n```\n\n```expected-output\nHigh/Low Temperature : Temperatures\n--------\nhigh  77\nlow   60\n--------\n```\n\n#### Copy of 2 earlier examples in REPL for testing on Python 3.7\n\n```python\n\u003e\u003e\u003e @dataclass\n... class MoreConditions:\n...     visibility: float = field(metadata=stow(help=\"(mi)\",spec=\".2f\"))\n...     dewpoint: int = field(metadata=stow(help=\"(degF)\"))\n\u003e\u003e\u003e\n\u003e\u003e\u003e more_data = MoreConditions(visibility=10.00,dewpoint=71)\n\u003e\u003e\u003e dataclass_print(more_data)\n     MoreConditions\n-----------------------\nvisibility  (mi)  10.00\ndewpoint  (degF)     71\n-----------------------\n\u003e\u003e\u003e\n\u003e\u003e\u003e @dataclass\n... class MoreCurrentConditions:\n...     temperature: float\n...     humidity: float\n...     heat_index: int\n...     wind: Wind = field(metadata=stow(help=\"(2pm)\"))\n\u003e\u003e\u003e\n\u003e\u003e\u003e more_weather_data = MoreCurrentConditions(\n...     80.0, 0.71, 83, Wind(11, Direction.E)\n...     )\n\u003e\u003e\u003e dataclass_print(more_weather_data)\nMoreCurrentConditions\n-----------------\ntemperature  80.0\nhumidity     0.71\nheat_index     83\nwind  (2pm)  Wind\n-----------------\n\u003cBLANKLINE\u003e\n  MoreCurrentConditions.wind  (2pm) : Wind\n  -------------\n  speed      11\n  direction   E\n  -------------\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftmarktaylor%2Fmonotable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftmarktaylor%2Fmonotable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftmarktaylor%2Fmonotable/lists"}