Skip to main content

cleanmonkey

One-call text cleanup for invisible characters, smart quotes, and whitespace normalization.

Install

pip install cleanmonkey

Quick Start

from cleanmonkey import clean

# Sensible defaults handle the common garbage
clean("hello\u00a0world\u2019s \u2014 test")
# → "hello world's - test"

# Idempotent — safe to call twice
clean(clean(text)) == clean(text)

What It Cleans (by default)

Category Examples Result
Non-breaking spaces \u00a0, \u2007, \u202f Regular space
Zero-width chars \u200b, \u200c, \u200d, \ufeff Removed
Smart quotes \u2018 \u2019 \u201c \u201d ' and "
Dashes \u2013 (en), \u2014 (em) -
Ellipsis \u2026 ...
Control chars null, form feed, vertical tab Removed
Line endings \r\n, \r \n
Multiple spaces "hello world" "hello world"
Leading/trailing " hello " "hello"

Granular Control

Override any default:

clean(text, smart_quotes=False)       # keep curly quotes
clean(text, dashes=False)             # keep em/en dashes
clean(text, fullwidth=True)           # also normalize fullwidth digits/letters
clean(text, collapse_spaces=False)    # keep multiple spaces
clean(text, strip=False)              # keep leading/trailing whitespace

Profiles

clean(text, profile="default")     # all normalizations (the default)
clean(text, profile="csv")         # default + fullwidth normalization
clean(text, profile="sql")         # default + fullwidth normalization
clean(text, profile="display")     # keep smart quotes & dashes; still clean invisible, control, whitespace, line endings
clean(text, profile="minimal")     # invisible chars only, no collapsing or stripping
clean(text, profile="aggressive")  # everything including fullwidth

Batch Helpers

from cleanmonkey import clean_column, clean_dict

# Clean a list (non-strings pass through)
clean_column(["hello\u00a0world", 42, None])
# → ["hello world", 42, None]

# Recursively clean dict values
clean_dict({"name": "John\u00a0Doe", "nested": {"val": "test\u200b"}})
# → {"name": "John Doe", "nested": {"val": "test"}}

# Also clean keys
clean_dict({"key\u00a0name": "val"}, keys=True)
# → {"key name": "val"}

Inspect

Find out what's lurking in your text:

from cleanmonkey import inspect

for info in inspect("hello\u00a0world\u200b"):
    print(f"{info.codepoint} {info.name} count={info.count} at {info.positions}")
# U+00A0 NO-BREAK SPACE count=1 at [5]
# U+200B ZERO WIDTH SPACE count=1 at [11]

CLI

# Clean a file
cleanmonkey input.txt -o output.txt

# Pipe through stdin
cat dirty.csv | cleanmonkey > clean.csv

# Use a profile
cleanmonkey --profile csv input.txt

# Inspect mode — report what's in a file
cleanmonkey --inspect input.txt

# Machine-readable JSON inspect output
cleanmonkey --json input.txt

# Selective overrides
cleanmonkey --no-smart-quotes --fullwidth input.txt

# Preserve whitespace structure
cleanmonkey --no-strip --no-collapse-spaces input.txt

# Preserve line endings (CR/CRLF)
cleanmonkey --no-line-endings input.txt

Built for LLMs

cleanmonkey is designed to work well as a tool for large language models. Invisible character cleanup is a constant source of silent bugs in LLM-driven data pipelines — non-breaking spaces break splits, zero-width characters corrupt comparisons, and smart quotes fail exact matches. Without cleanmonkey, LLMs end up generating repetitive .replace() chains that miss edge cases and waste tokens. A single clean() call handles all of it with a structured, idempotent result — no multi-step prompting or character-by-character debugging required. Fewer tokens in, clean data out.

A note on whitespace

By default clean() strips each line and collapses runs of spaces, which is correct for prose but destroys indentation in structured text (YAML, Python, Markdown). Use clean(text, strip=False, collapse_spaces=False) or profile="minimal" for those. See LIMITATIONS.md for this and other deliberate design tradeoffs.

Quality & review

cleanmonkey is hardened with a competitive multi-model review methodology and a measurable release gate:

  • CONTRIBUTING.md — testing philosophy and the review-panel process.
  • LIMITATIONS.md — intentional tradeoffs reviewers should not re-litigate.
  • RELEASE_READINESS.md + release_readiness.json + scripts/readiness.py — the release rubric and convergence metric (python scripts/readiness.py).
  • REVIEW_HISTORY.md — how the library was hardened.

License

MIT

Metadata

Release files for cleanmonkey 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cleanmonkey 0.2.0
File Size Uploaded Provenance
cleanmonkey-0.2.0.tar.gz 33.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for cleanmonkey 0.2.0
File Interpreter ABI Platform
cleanmonkey-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 50.1 kB

Release files / cleanmonkey-0.2.0.tar.gz

Download URL cleanmonkey-0.2.0.tar.gz
Size 33.3 kB
Tags Source
SHA-256 checksum
How to use checksums
a0794bb74b7637d73b54d407f5c31a4cc210ee8299663a0d5c3d7b99710d8ab2
BLAKE2b-256 checksum
How to use checksums
f72f228c9cea05a45032aac6d71a89844d900b76af67ce3849ef4dab2906eca1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / cleanmonkey-0.2.0-py3-none-any.whl

Download URL cleanmonkey-0.2.0-py3-none-any.whl
Size 16.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
19f8d7b0c9a6f6dced558960f9db3aac7dc6dc66adfcf048a9a8df7a84739d46
BLAKE2b-256 checksum
How to use checksums
91a3fd2cfd5640d4b0ecff0aad63c5e3e01e2037a9d411ec2eb5fc4a2c04bbdb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Security for cleanmonkey 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page