text-iron
Dependency-free Persian/multilingual text normalization for search and matching
(queries, titles, body content). One implementation, pinned by NORM_VERSION, so
text normalized at different times stays byte-identical — drift silently
breaks matching.
Use
from text_iron import normalize_query, normalize_title, normalize_content
normalize_query("Café كيك ۱۲۳") # -> "cafe کیک 123"
normalize_title("کتاب: جلد ۲") # -> "کتاب: جلد 2"
normalize_content("بند اول\n\nبند دوم") # -> keeps the paragraph break
The output is a matching / embedding key, not display text. Always keep the original around for display and snippets.
URLs
text_iron.url is a URL normalizer for whatever keys URLs — a crawler's seen-set, an index,
a store of search results — so that everything meets on one key:
from text_iron.url import normalize_url, URL_NORMALIZATION_VERSION
normalize_url("HTTP://Example.IR:80/a/./b?utm_source=x&b=2&a=1#top").value
# -> "http://example.ir/a/b?a=1&b=2"
It is not text normalization and uses none of it: a URL is an identifier, and folding its
letters or digits would change it. Its rules are versioned by URL_NORMALIZATION_VERSION,
separately from NORM_VERSION.
Pipelines
| function | scripts kept | punctuation | whitespace |
|---|---|---|---|
normalize_query |
Persian/Arabic + Latin | none (letters+digits key) | flattened to one line |
normalize_title |
all | sentence punctuation | flattened to one line |
normalize_content |
all | sentence punctuation | line/paragraph structure preserved |
All three share one folding core and are idempotent.
Components
Composable, single-purpose, pure: to_unicode_form, fold_persian_letters,
strip_arabic_diacritics, fold_latin_diacritics, normalize_digits,
to_lowercase, canonicalize_zwnj, filter_charset (via CharPolicy),
flatten_whitespace, normalize_content_whitespace, fingerprint. Build a new
pipeline by composing these, then pin a new NORM_VERSION.
Design decisions worth knowing
- Homophones (
س/ص/ث,ز/ذ/ض/ظ, …) are NOT folded — they are distinct letters and real spelling signal. - Hamza forms (
أ/إ/ؤ/ئ),ة,ۀare NOT folded — conservative default; folding raises recall. Flip infold_persian_letters/ the table if desired. - NFKC is used, which rewrites
m²→m2,½→1⁄2,①→1. Switch a pipeline's_fold(..., unicode_form="NFC")if a use case must keep those glyphs. - Query drops non-Persian/Latin scripts; content keeps every script. The
charset policy is the main knob (
CharPolicy).
Install
pip install text-iron
Test
uv run pytest tests # or:
python tests/test_text_iron.py
Metadata
Release files for text-iron 1.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| text_iron-1.1.1.tar.gz | 18.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| text_iron-1.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 35.6 kB
Release files / text_iron-1.1.1.tar.gz
| Download URL | text_iron-1.1.1.tar.gz |
|---|---|
| Size | 18.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
282b3f14df50c47e0d30f1512d38c3e743c23954fca829885605a578ae658e15
|
|
BLAKE2b-256 checksum How to use checksums |
f71a5fd52fc8f8c217a9d3f0d5ae9910541656b3a6e1230f092edb7525086bbe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / text_iron-1.1.1-py3-none-any.whl
| Download URL | text_iron-1.1.1-py3-none-any.whl |
|---|---|
| Size | 17.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ded426d4671b58bae98072e70578eeba9b128a13a3f64bc7e655d023f5e51758
|
|
BLAKE2b-256 checksum How to use checksums |
6134ea9d7be1878cfc82de79fef33a41410822c44471c5a903dd0a37ff8697b3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|