{"id":16893201,"url":"https://github.com/gruns/undent","last_synced_at":"2025-10-07T08:31:33.675Z","repository":{"id":62586275,"uuid":"340767303","full_name":"gruns/undent","owner":"gruns","description":"⬅️ Dedent and format source code strings into their intended human-readable strings.","archived":false,"fork":false,"pushed_at":"2024-01-04T15:19:39.000Z","size":30,"stargazers_count":20,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-09-02T17:52:26.012Z","etag":null,"topics":["dedent","format","formatter","indent","indentation","python","string-manipulation","strings","text"],"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/gruns.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","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":"2021-02-20T22:31:16.000Z","updated_at":"2025-04-20T17:35:01.000Z","dependencies_parsed_at":"2024-10-28T12:59:51.434Z","dependency_job_id":"618b910b-1f01-4e62-80d5-1f40139cb1c6","html_url":"https://github.com/gruns/undent","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gruns/undent","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gruns%2Fundent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gruns%2Fundent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gruns%2Fundent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gruns%2Fundent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gruns","download_url":"https://codeload.github.com/gruns/undent/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gruns%2Fundent/sbom","scorecard":{"id":446831,"data":{"date":"2025-08-11","repo":{"name":"github.com/gruns/undent","commit":"574764a6008a23bdc8bd2c6a620ae547fdc80cf9"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"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":"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":"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":"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/26 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":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"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":"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":"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":"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":"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.txt:0","Info: FSF or OSI recognized license: MIT License: LICENSE.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"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"}}]},"last_synced_at":"2025-08-19T06:58:02.595Z","repository_id":62586275,"created_at":"2025-08-19T06:58:02.595Z","updated_at":"2025-08-19T06:58:02.595Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278743159,"owners_count":26037986,"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","status":"online","status_checked_at":"2025-10-07T02:00:06.786Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["dedent","format","formatter","indent","indentation","python","string-manipulation","strings","text"],"created_at":"2024-10-13T17:14:00.975Z","updated_at":"2025-10-07T08:31:33.391Z","avatar_url":"https://github.com/gruns.png","language":"Python","readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"logo.svg\" width=\"300px\" height=\"200px\" alt=\"Undent\"\u003e\n\u003c/div\u003e\n\n# Undent\n\nUndent turns strings stored in source code, which may have newlines,\ntabs, and whitespace inserted to adhere to code formatting and linting\nrules, into human-readable strings.\n\nStrings in source code may be indented, bookended with whitespace, or\ncontain newlines to adhere to code style guidelines. `undent()`\ngracefully removes such code style formatting and returns the original,\nintended string for human consumption.\n\nTo accomplish this, `undent()`\n\n  1. [Dedents](https://docs.python.org/3/library/textwrap.html#textwrap.dedent)\n     the multiline string to remove common indentation.\n\n  2. Strips preceeding and trailing whitespace, while preserving\n     post-dedent indentation, to remove whitespace added for source code\n     formatting.\n\n  3. Unwraps paragraphs to remove newlines inserted for source code\n     formatting. E.g. newlines inserted to adhere to PEP 8's 79\n     characters per line limit.\n\n     Or, optionally line wrap paragraphs to a custom width, e.g. 72\n     character per line.\n\n\n### Usage\n\nJust import `undent()` and give it a multiline string.\n\n```python\nfrom undent import undent\n\ndef createEmail():\n    name = 'Billy'\n    emailAddr = 'billy@gmail.com'\n    email = undent(f'''\n        Hi {name}!\n\n        Thank you for registering with email address\n\n          {emailAddr}\n\n        We'd love to hear from you; please email us\n        and say hello!''')\n\n   return email\n```\n\nAbove, `undent()` dedents, formats, and wraps the multiline string into\na beautiful, human-readable string.\n\n```\nHi Billy!\n\nThank you for registering with email address\n\n  billy@gmail.com.\n\nWe'd love to hear from you; please email us and say hello!\n```\n\n`undent(s, width=False, strip=True)` takes two, optional arguments.\n\n#### width\n\n(default: `False`) `width` is the maximum length of wrapped lines, in\ncharacters, or `False` to unwrap lines. If `width` is an integer, as\nlong as there are no individual words in the input string longer than\n`width`, no output line will be wider than `width` characters. Examples:\n\n```python\nundent('Once upon a time, there was a little girl named Goldilocks.', width=30)\n```\n\nreturns\n\n```\nOnce upon a time, there was a\nlittle girl named Goldilocks.\n```\n\nConversely,\n\n```python\nundent('''Once upon a time, there was a\nlittle girl named Goldilocks.''', width=False)\n```\n\nreturns\n\n```\nOnce upon a time, there was a little girl named Goldilocks.\n```\n\n#### strip\n\n(default: `True`) `strip` determines whether or not to remove preceeding\nand trailing whitespace. Examples:\n\n```python\nundent('''\n    Once upon a time, there was a\n    little girl named Goldilocks.\n    ''', strip=True)\n```\n\nreturns\n\n```\nOnce upon a time, there was a little girl named Goldilocks.\n````\n\nAlternatively\n\n```python\nundent('''\n\n    Once upon a time, there was a\n    little girl named Goldilocks.\n\n    ''', strip=False)\n```\n\nreturns\n\n```\n\n\nOnce upon a time, there was a little girl named Goldilocks.\n\n\n```\n\n\n### Examples\n\n#### `undent()` [dedents](https://docs.python.org/3/library/textwrap.html#textwrap.dedent) the string so indentation added for source code formatting isn't preserved.\n\n```python\nif True:\n    print(undent('''common\n\n    indentation\n\nis removed'''))\n```\n\noutputs\n\n```\ncommon\n\n    indentation\n\nis removed\n```\n\n#### `undent()` strips preceeding and trailing whitespace, while preserving post-dedent indentation, so whitespace added for source code formatting isn't unintentionally preserved.\n\n```python\nif True:\n    print(undent('''\n        preceeding\n\n            and trailing\n\n        whitespace is removed\n    '''))\n```\n\noutputs\n\n```\npreceeding\n\n    and trailing\n\nwhitespace is removed\n```\n\n#### `undent()` unwraps paragraphs so newlines inserted for source code formatting aren't unintentionally preserved in the output, e.g. newlines inserted to avoid lines wider than PEP 8's 80 characters per line.\n\n```python\nif someIndentation:\n    if moreIndentation:\n        if evenDeeperIndentation:\n            print(undent(f'''\n                Once upon a time, there was a little girl named\n                Goldilocks. She went for a walk in the forest. Pretty\n                soon, she came upon a house. She knocked and, when no\n                one answered, she walked right in.\n            \n                At the table in the kitchen, there were three bowls of\n                porridge. Goldilocks was hungry. She tasted the porridge\n                from the first bowl.\n            '''))\n```\n\noutputs\n\n```\nOnce upon a time, there was a little girl named Goldilocks. She went for a walk in the forest. Pretty soon, she came upon a house. She knocked and, when no one answered, she walked right in.\n\nAt the table in the kitchen, there were three bowls of porridge. Goldilocks was hungry. She tasted the porridge from the first bowl.\n```\n\n#### Or, optionally line wrap output paragraphs to your intended width, e.g. 72 character per line.\n\n```python\nif someIndentation:\n    if moreIndentation:\n        if evenDeeperIndentation:\n            width = 72\n            print(undent(f'''\n                Once upon a time, there was a little girl named\n                Goldilocks. She went for a walk in the forest. Pretty\n                soon, she came upon a house. She knocked and, when no\n                one answered, she walked right in.\n            \n                At the table in the kitchen, there were three bowls of\n                porridge. Goldilocks was hungry. She tasted the porridge\n                from the first bowl.\n            ''', width))\n```\n\noutputs\n\n```\nOnce upon a time, there was a little girl named Goldilocks. She went for\na walk in the forest. Pretty soon, she came upon a house. She knocked\nand, when no one answered, she walked right in.\n\nAt the table in the kitchen, there were three bowls of porridge.\nGoldilocks was hungry. She tasted the porridge from the first bowl.\n```\n\n\n### Installation\n\nInstalling Undent with pip is easy.\n\n```\n$ pip install undent\n```","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgruns%2Fundent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgruns%2Fundent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgruns%2Fundent/lists"}