Skip to main content

prosemeter

CI License: MIT Python 3.10–3.13

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 — an AI social media manager for small businesses. You record one short voice note a week; Laspi turns it into a week of ready-to-publish posts — captions written natively per network, images and short videos — in English, Spanish, Russian or Italian. These metrics are part of how Laspi keeps that writing sounding human.

The measuring is open source. The writing is the product: try a free week at laspi.pro — no card needed.

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.0.tar.gz (81.5 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.0-py3-none-any.whl (18.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: prosemeter-0.1.0.tar.gz
  • Upload date:
  • Size: 81.5 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.0.tar.gz
Algorithm Hash digest
SHA256 ac9b9085d9f0b27fb9ac0861167dfc573a62c9351901e6dbefb4016c039de560
MD5 b73c14237df5865b562bf30ad6ed41db
BLAKE2b-256 301b8755017c7a2eff5d17f04151c7fee984d1d373d3d99de511f82949bfd91e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: prosemeter-0.1.0-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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ec439163dd106ebc61561485f0c31d10ac5984516e96e8e84f4c1f35b02c9cf8
MD5 2779209c40343366fc8a7deeab2cd258
BLAKE2b-256 a21b9cc508869c961a9ff0baa693b3299f5935bcbaf3b62dc32c383373f85ba6

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.2

2 files

0.1.1

2 files

This release

0.1.0 This release

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