Skip to main content

prosemeter

CI License: MIT PyPI Python

A ruler for prose texture in Russian, English, Spanish and Italian. Pure stdlib, zero dependencies.

prosemeter measures the surface texture of a text — sentence rhythm, punctuation habits, lexical texture, voice — and hands you a flat dict of numbers. That's the whole product.

It is explicitly not an AI detector and not a quality metric: it describes, it does not pass judgment. Some of the features it reports (filler density, contrast frames, opener repetition) happen to be popular tells of generated or padded prose, but prosemeter attaches no verdict to any value. What counts as "too much" depends on your corpus, your genre and your taste — that's your call, on your data.

Install

pip install prosemeter

Usage

from prosemeter import profile

text = (
    "The kettle clicked off and the kitchen went quiet. I had been rewriting "
    "the same paragraph for an hour, and it still read like a brochure. So I "
    "did what editors do: cut the openers, moved the numbers up front, and "
    "read it aloud. Better. Not perfect, but better."
)

print(profile(text))          # lang="auto" detects English here
print(profile(text, lang="en"))  # or say it explicitly

Real output (English adds five extra keys on top of the common core):

{
  "words": 49, "sentences": 5,
  "mean_sentence_len": 9.8, "cv_sentence_len": 0.69,
  "pct_short": 0.4, "pct_long": 0.0, "staccato_share": 0.4,
  "anaphora_top_share": 0.2,
  "dash_per_100w": 0.0, "guillemet_per_100w": 0.0, "questions_per_sent": 0.0,
  "contrast_frames_per_100w": 0.0,
  "address_per_1k": 0.0, "first_person_per_1k": 40.8,
  "digit_density_per_1k": 0.0,
  "filler_per_100w": 0.0, "nominal_per_100w": 0.0,
  "mean_word_len": 4.14, "ttr": 0.8,
  "syllables_per_word": 1.33, "flesch_reading_ease": 84.7,
  "polysyllable_per_100w": 0.0, "passive_per_100sent": 0.0,
  "ly_adverbs_per_100w": 0.0
}

The public API is three names: profile(text, lang="auto"), SUPPORTED_LANGS (("ru", "en", "es", "it")) and __version__. lang="auto" uses a cheap script/function-word heuristic that is reliable on a paragraph of ordinary prose; pass the language explicitly for short fragments or mixed-language text.

Features

Counts are ints; every other value is a rate, so profiles of texts of different lengths are comparable. Rates are per word (per_100w / per_1k), per sentence (per_sent / per_100sent) or a share in 0..1.

Key What it measures Languages
words Word count. all
sentences Sentence count (regex splitter — see Honest limits). all
mean_sentence_len Mean sentence length in words. all
cv_sentence_len Coefficient of variation (std/mean) of sentence length — the classic dispersion measure used as a rhythm signal. Metronomic prose sits low; prose alternating long and short sentences sits higher. all
pct_short Share of sentences with ≤ 6 words. all
pct_long Share of sentences with ≥ 25 words. all
staccato_share Share of stub sentences (≤ 4 words) — the "Short. Punchy. Fragments." register. all
anaphora_top_share Opener repetition: share of sentences beginning with the single most frequent opening word ("This… This… This…"). English baselines are naturally noisy (articles, pronouns). all
dash_per_100w Em/en dashes (plus the spaced hyphen used as a dash) per 100 words. Dash-for-everything punctuation vs. dash-as-rare-accent. all
guillemet_per_100w Guillemets («») per 100 words — quote/dialogue-heavy vs. plain expository prose. all
questions_per_sent Question marks per sentence — rhetorical-question density. all
contrast_frames_per_100w Density of the "it's not X, it's Y" contrast frame (per-language patterns). One is rhetoric; a high rate is a texture of its own. all
address_per_1k Second-person reader-address words per 1000 words. all
first_person_per_1k First-person words per 1000 words — personal voice. all
digit_density_per_1k Numeric tokens per 1000 words — concreteness of the text's factual grounding. all
filler_per_100w Hits from a per-language filler/officialese phrase list per 100 words ("it is important to note", «важно отметить», "cabe destacar", "va sottolineato"). The Russian list follows the officialese-hunting tradition of Nora Gal. all
nominal_per_100w Abstract nominalizations per 100 words, matched by derivational suffix ("-tion", "-ность", "-ción", "-zione") — Helen Sword's "zombie nouns", Nora Gal's hidden verbs. all
mean_word_len Mean word length in characters. all
ttr Type-token ratio — lexical diversity. Length-sensitive: only compare texts of similar length. all
syllables_per_word Mean syllables per word (heuristic counter). en
flesch_reading_ease Flesch Reading Ease (Rudolf Flesch, 1948): higher = plainer. en
polysyllable_per_100w Words with ≥ 4 syllables per 100 words. en
passive_per_100sent Passive constructions ("to be" + past participle, regex approximation) per 100 sentences — the Orwell / Strunk & White signal. en
ly_adverbs_per_100w -ly adverbs per 100 words — the modifier crutch Stephen King warns about. en

Honest limits

Tokenization is regex-only: sentences split on runs of .!?, words on per-language character classes. Abbreviations, decimals and ellipses can over- or under-split. Over a paragraph or an article these errors average out; do not trust the numbers on a single sentence, and do not compare ttr across texts of very different lengths.

Scope is frozen

This package does one thing: it measures. Bug reports (wrong counts, crash on valid input, broken language detection) are very welcome. Feature requests — new languages, new metrics, verdicts of any kind — are out of scope for now.

Built to power Laspi

Laspi

prosemeter is the measuring half of the writing engine behind Laspi — a marketing employee in a small-business owner's phone. Laspi keeps a living memory of the business (every fact confirmed by the owner), writes platform-native posts, images and short videos from it, and looks after the business's visibility in AI answers — in whatever language the business sells in. These metrics are part of how Laspi keeps that writing sounding human.

The measuring is open source. The writing is the product: laspi.pro.

License

MIT © 2026 GradeBuilder S.L.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

prosemeter-0.1.2.tar.gz (81.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

prosemeter-0.1.2-py3-none-any.whl (18.1 kB view details)

Uploaded Python 3

File details

Details for the file prosemeter-0.1.2.tar.gz.

File metadata

  • Download URL: prosemeter-0.1.2.tar.gz
  • Upload date:
  • Size: 81.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for prosemeter-0.1.2.tar.gz
Algorithm Hash digest
SHA256 b51033d00e6198811415dfc098d30a7a71d22f54f37ed6ae43180f01ed8936a5
MD5 b653ba11ede935919121f26d26228cb2
BLAKE2b-256 d863807e3b5a64180158f3c1df9dba7f559b3fe4307cef06cb8ed0e271293804

See more details on using hashes here.

File details

Details for the file prosemeter-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: prosemeter-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 18.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for prosemeter-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 600826212cb3c662dfe97c8eef3b1eb5d414842087c3276a2c50ddfe5ad84f68
MD5 101f902c06c2744875a8e05715e4e440
BLAKE2b-256 31d23df72aba8a7c9eccd97f3e2721a254e35a8879960b31520f71d040737b58

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page