pyests 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ # Python
2
+ __pycache__/
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ target/
7
+
8
+ # Environments
9
+ .venv/
10
+ venv/
11
+ .env
12
+
13
+ # Tools
14
+ .coverage
15
+ coverage.xml
16
+ .mypy_cache
17
+ .pytest_cache
18
+ .ruff_cache
19
+ .ipynb_checkpoints
20
+
21
+ # Data and documentation
22
+ ests_data
23
+ site/
24
+
25
+ # Editors and OS
26
+ .vscode
27
+ .idea
28
+ .DS_Store
@@ -0,0 +1,17 @@
1
+ MIT License
2
+ Copyright (c) 2026 Sergey Shkarin
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+ The above copyright notice and this permission notice shall be included in all
10
+ copies or substantial portions of the Software.
11
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17
+ SOFTWARE.
pyests-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,395 @@
1
+ Metadata-Version: 2.5
2
+ Name: pyests
3
+ Version: 0.1.0
4
+ Summary: Spanish Texts Statistics
5
+ Project-URL: Homepage, https://github.com/SergeyShk/esTS
6
+ Project-URL: Repository, https://github.com/SergeyShk/esTS
7
+ Project-URL: Documentation, https://sergeyshk.github.io/esTS/
8
+ Project-URL: Issues, https://github.com/SergeyShk/esTS/issues
9
+ Author-email: Sergey Shkarin <kouki.sergey@gmail.com>
10
+ Maintainer-email: Sergey Shkarin <kouki.sergey@gmail.com>
11
+ License-Expression: MIT
12
+ License-File: LICENSE.txt
13
+ Keywords: CL,NLP,analytics,computational,language,linguistics,natural,processing,spanish,text
14
+ Classifier: Development Status :: 2 - Pre-Alpha
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Intended Audience :: Education
17
+ Classifier: Intended Audience :: Information Technology
18
+ Classifier: Intended Audience :: Science/Research
19
+ Classifier: Natural Language :: Spanish
20
+ Classifier: Operating System :: OS Independent
21
+ Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3 :: Only
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Programming Language :: Python :: 3.13
26
+ Classifier: Programming Language :: Python :: 3.14
27
+ Classifier: Topic :: Text Processing
28
+ Classifier: Topic :: Text Processing :: Linguistic
29
+ Classifier: Typing :: Typed
30
+ Requires-Python: >=3.11
31
+ Requires-Dist: numpy>=1.26
32
+ Requires-Dist: scipy>=1.11
33
+ Requires-Dist: simplemma>=1.0
34
+ Requires-Dist: spacy>=3.7
35
+ Description-Content-Type: text/markdown
36
+
37
+ <h1 align="center">esTS</h1>
38
+
39
+ <p align="center">
40
+ <b>Spanish Texts Statistics</b> - a library for statistics extraction from texts in Spanish
41
+ </p>
42
+
43
+ <p align="center">
44
+ <a href="https://sergeyshk.github.io/esTS/">Documentation</a> ·
45
+ <a href="https://pypi.org/project/pyests/">PyPI</a> ·
46
+ <a href="https://github.com/SergeyShk/esTS/blob/master/README.es.md">Español</a>
47
+ </p>
48
+
49
+ <p align="center">
50
+ <a href="https://pypi.org/project/pyests/"><img src="https://img.shields.io/pypi/v/pyests?logo=pypi&logoColor=FFE873" alt="Version"></a>
51
+ <a href="https://pypi.org/project/pyests/"><img src="https://img.shields.io/pypi/pyversions/pyests.svg?logo=python&logoColor=FFE873" alt="Supported Python versions"></a>
52
+ <a href="https://github.com/SergeyShk/esTS/actions/workflows/ci.yml"><img src="https://github.com/SergeyShk/esTS/actions/workflows/ci.yml/badge.svg" alt="Build"></a>
53
+ <a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff"></a>
54
+ <a href="https://github.com/SergeyShk/esTS/blob/master/LICENSE.txt"><img src="https://img.shields.io/github/license/sergeyshk/esTS.svg" alt="License"></a>
55
+ </p>
56
+
57
+ ---
58
+
59
+ **esTS** computes for Spanish texts what usually requires assembling several separate tools: basic statistics, readability and lexical diversity - by published formulas with the coefficients and the scales of their authors, deterministically and without a neural network inside.
60
+
61
+ The library works both with raw strings and with `Doc` objects of [spaCy](https://github.com/explosion/spaCy), and needs no trained model: sentences, words and character N-grams are extracted by rules, syllables and stress follow from the orthography.
62
+
63
+ * **[Object extraction](https://sergeyshk.github.io/esTS/extractors/sentences/)** - configurable sentence, word and character N-gram tokenizers that know the inverted marks, the dialogue dash and the abbreviations of Spanish
64
+ * **[Syllables and stress](https://sergeyshk.github.io/esTS/syllables/)** - rule-based syllabification and the stressed syllable derived from the spelling, with no dictionary
65
+ * **[Basic statistics](https://sergeyshk.github.io/esTS/stats/basic_stats/)** - counts of sentences, words, letters, syllables and punctuation marks by type, with distributions and normalized shares
66
+ * **[Readability metrics](https://sergeyshk.github.io/esTS/stats/readability_stats/)** - Fernández Huerta, Szigriszt-Pazos with the INFLESZ scale, Gutiérrez de Polini, Crawford, Legibilidad µ, SOL, LIX and RIX, with a consensus grade, the school stages of Spain and reading time
67
+ * **[Lexical diversity metrics](https://sergeyshk.github.io/esTS/stats/diversity_stats/)** - TTR and its variations, MATTR, MSTTR, MTLD, HD-D, Simpson's and Yule's indices, entropy, Zipf's and Heaps' laws
68
+
69
+ Morphology, syntax and cohesion on Universal Dependencies come in 0.2, corpus measures and stylometry in 0.3, style, phonostatistics, metre and rhyme in 0.4.
70
+
71
+ ## Installation
72
+
73
+ Requires Python 3.11 or newer.
74
+
75
+ ```bash
76
+ pip install pyests
77
+ ```
78
+
79
+ Or with [uv](https://docs.astral.sh/uv/):
80
+
81
+ ```bash
82
+ uv add pyests
83
+ ```
84
+
85
+ The distribution on PyPI is `pyests`, the package it installs is `ests`. No spaCy model is needed for the statistics of 0.1; one is needed only to parse a text yourself and pass the `Doc` instead of a string:
86
+
87
+ ```bash
88
+ python -m spacy download es_core_news_sm
89
+ ```
90
+
91
+ ## Quick start
92
+
93
+ ```python
94
+ >>> from ests import BasicStats, DiversityStats, ReadabilityStats
95
+
96
+ >>> text = "Hay tres clases de mentiras: mentiras, malditas mentiras y estadísticas"
97
+
98
+ >>> BasicStats(text).get_stats()
99
+ {'c_letters': {1: 1, 2: 1, 3: 1, 4: 1, 6: 1, 8: 4, 12: 1},
100
+ 'c_syllables': {1: 4, 2: 1, 3: 4, 5: 1},
101
+ 'n_sents': 1,
102
+ 'n_words': 10,
103
+ 'n_unique_words': 8,
104
+ 'n_long_words': 5,
105
+ 'n_complex_words': 5,
106
+ 'n_simple_words': 5,
107
+ 'n_monosyllable_words': 4,
108
+ 'n_polysyllable_words': 6,
109
+ 'n_chars': 71,
110
+ 'n_letters': 60,
111
+ 'n_spaces': 9,
112
+ 'n_syllables': 23,
113
+ 'n_punctuations': 2,
114
+ 'c_punctuations': {'comma': 1, 'period': 0, 'question': 0, 'exclamation': 0,
115
+ 'ellipsis': 0, 'colon': 1, 'semicolon': 0, 'dash': 0,
116
+ 'hyphen': 0, 'angle_quotes': 0, 'straight_quotes': 0,
117
+ 'parentheses': 0, 'other': 0}}
118
+
119
+ >>> ReadabilityStats(text).flesch_reading_easy
120
+ 53.545000000000016
121
+
122
+ >>> DiversityStats(text).ttr
123
+ 0.8
124
+ ```
125
+
126
+ ## Features
127
+
128
+ ### Object extraction
129
+
130
+ The library allows creating your own tools for sentence, word and character N-gram extraction from a text, which can be further employed for counting statistics. The sentence splitter knows the inverted marks, the dash of a line of dialogue with the remark of the narrator, the abbreviations and the initials of Spanish; the word tokenizer keeps clitics, ordinals and numbers written the Spanish way together, and lemmas come from [simplemma](https://github.com/adbar/simplemma), which needs no model.
131
+
132
+ ```python
133
+ >>> from ests import CharNgramsExtractor, SentsExtractor, WordsExtractor
134
+
135
+ >>> SentsExtractor().extract("—¿Vienes? —preguntó María. ¡Claro que sí!")
136
+ ('—¿Vienes? —preguntó María.', '¡Claro que sí!')
137
+
138
+ >>> we = WordsExtractor(use_lexemes=True, stopwords=["de", "y"], filter_nums=True, ngram_range=(1, 2))
139
+ >>> we.extract("Hay 3 clases de mentiras y estadísticas")
140
+ ('haber', 'clase', 'mentira', 'estadística', 'haber_clase', 'clase_mentira', 'mentira_estadística')
141
+
142
+ >>> CharNgramsExtractor(n=3, lowercase=True).extract("estadísticas")[:5]
143
+ ('est', 'sta', 'tad', 'adí', 'dís')
144
+ ```
145
+
146
+ More in the [documentation](https://sergeyshk.github.io/esTS/extractors/sentences/).
147
+
148
+ <details>
149
+ <summary><b>Syllables and stress</b></summary>
150
+
151
+ <br>
152
+
153
+ Spanish spelling encodes both the syllable boundaries and the stress, so the library needs no dictionary: diphthongs, hiatuses and triphthongs, the silent `u` of `qu` and `gu`, the vocalic `y`, the `h` inside a diphthong and the consonant clusters give the syllables; the written accent, or the ending of the word when there is none, gives the stressed syllable. Adverbs in `-mente` and hyphenated compounds carry two stresses.
154
+
155
+ ```python
156
+ >>> from ests.syllables import stress_type, syllabify, word_stress, word_stresses
157
+
158
+ >>> syllabify("murciélago")
159
+ ['mur', 'cié', 'la', 'go']
160
+
161
+ >>> syllabify("averiguáis")
162
+ ['a', 've', 'ri', 'guáis']
163
+
164
+ >>> word_stress("construir"), stress_type("construir")
165
+ (1, 'aguda')
166
+
167
+ >>> word_stresses("fácilmente")
168
+ [0, 2]
169
+ ```
170
+
171
+ More in the [documentation](https://sergeyshk.github.io/esTS/syllables/).
172
+
173
+ </details>
174
+
175
+ <details>
176
+ <summary><b>Basic statistics</b></summary>
177
+
178
+ <br>
179
+
180
+ The library allows extracting the following statistics from a text:
181
+
182
+ * the number of sentences
183
+ * the number of words
184
+ * the number of unique words
185
+ * the number of long words
186
+ * the number of complex words
187
+ * the number of simple words
188
+ * the number of monosyllable words
189
+ * the number of polysyllable words
190
+ * the number of characters
191
+ * the number of letters
192
+ * the number of spaces
193
+ * the number of syllables
194
+ * the number of punctuation marks and their distribution by type
195
+ * the distribution of words by the number of letters
196
+ * the distribution of words by the number of syllables
197
+
198
+ A complex word has three or more syllables and a long word seven or more letters, as the Spanish readability formulas count them. Any statistic can be printed in a readable form:
199
+
200
+ ```python
201
+ >>> from ests import BasicStats
202
+
203
+ >>> text = "Hay tres clases de mentiras: mentiras, malditas mentiras y estadísticas"
204
+ >>> BasicStats(text).print_stats()
205
+ Statistic | Value
206
+ ------------------------------
207
+ Sentences | 1
208
+ Words | 10
209
+ Unique words | 8
210
+ Long words | 5
211
+ Complex words | 5
212
+ Simple words | 5
213
+ Monosyllabic words | 4
214
+ Polysyllabic words | 6
215
+ Characters | 71
216
+ Letters | 60
217
+ Spaces | 9
218
+ Syllables | 23
219
+ Punctuation marks | 2
220
+ ```
221
+
222
+ More in the [documentation](https://sergeyshk.github.io/esTS/stats/basic_stats/).
223
+
224
+ </details>
225
+
226
+ <details>
227
+ <summary><b>Readability metrics</b></summary>
228
+
229
+ <br>
230
+
231
+ The library allows counting the following readability metrics:
232
+
233
+ * Flesch reading ease with the coefficients of Szigriszt-Pazos or of Fernández Huerta
234
+ * Gutiérrez de Polini comprehensibility formula
235
+ * Crawford grade
236
+ * Legibilidad µ
237
+ * SOL grade, the SMOG index converted to Spanish
238
+ * LIX readability measure
239
+ * RIX readability measure
240
+
241
+ An interpretation layer works on top of the formulas: the band of a scale for the reading ease and for Legibilidad µ, a consensus grade as the median of the grade formulas, the school stage and the reader age of Spain, and reading time by the norms of Spanish-speaking readers.
242
+
243
+ The coefficients of the Flesch reading ease are selected by the `preset` argument: by default the *fórmula de perspicuidad* of Szigriszt-Pazos with the INFLESZ scale validated on texts for patients (`general`); the coefficients of Fernández Huerta with the bands of their author are available as `classic`.
244
+
245
+ ```python
246
+ >>> from pprint import pprint
247
+ >>> from ests import ReadabilityStats
248
+
249
+ >>> text = "Hay tres clases de mentiras: mentiras, malditas mentiras y estadísticas"
250
+ >>> rs = ReadabilityStats(text)
251
+
252
+ >>> pprint(rs.get_stats(), sort_dicts=False)
253
+ {'flesch_reading_easy': 53.545000000000016,
254
+ 'gutierrez_polini_index': 33.5,
255
+ 'crawford_grade': 5.812999999999999,
256
+ 'mu_index': 50.943396226415096,
257
+ 'sol_grade': 9.258359866374562,
258
+ 'lix': 60.0,
259
+ 'rix': 5.0,
260
+ 'consensus_grade': 9.0,
261
+ 'reading_time': 0.03597122302158273}
262
+
263
+ >>> rs.print_stats()
264
+ Metric | Value
265
+ -------------------------------------------------------
266
+ Flesch reading ease (Szigriszt-Pazos) | 53.55
267
+ Gutiérrez de Polini comprehensibility | 33.50
268
+ Crawford grade | 5.81
269
+ Legibilidad µ | 50.94
270
+ SOL grade (SMOG for Spanish) | 9.26
271
+ LIX readability index | 60.00
272
+ RIX readability index | 5.00
273
+ Consensus grade | 9.00
274
+ Reading time (min) | 0.04
275
+
276
+ >>> rs.describe_level()
277
+ 'algo difícil'
278
+
279
+ >>> rs.describe_grade()
280
+ 'ESO (12-16 years)'
281
+ ```
282
+
283
+ More in the [documentation](https://sergeyshk.github.io/esTS/stats/readability_stats/).
284
+
285
+ </details>
286
+
287
+ <details>
288
+ <summary><b>Lexical diversity metrics</b></summary>
289
+
290
+ <br>
291
+
292
+ The library allows counting 32 lexical diversity metrics, among them:
293
+
294
+ * Type-Token Ratio and its variations: RTTR, CTTR, Herdan, Summer, Maas, Dugast
295
+ * Moving Average Type-Token Ratio and Mean Segmental Type-Token Ratio
296
+ * Measure of Textual Lexical Diversity and its moving-window variants MA-MTLD and MTLD-W
297
+ * Hypergeometric Distribution D
298
+ * Simpson's index, its reciprocal and the Gini-Simpson index
299
+ * the hapax index (Honoré's R), the measures of Yule, Herdan, Sichel, Michéa, Brunet, Dugast and Baayen
300
+ * Shannon entropy, evenness and perplexity
301
+ * the slope of Zipf's law, the Zipf-Mandelbrot fit and the exponent of Heaps' law
302
+
303
+ Any metric can be computed over windows of equal length, which is the standard way to compare texts of different lengths: the mean over the windows comes with a confidence interval.
304
+
305
+ ```python
306
+ >>> from ests import DiversityStats
307
+
308
+ >>> text = "Hay tres clases de mentiras: mentiras, malditas mentiras y estadísticas"
309
+ >>> ds = DiversityStats(text)
310
+
311
+ >>> ds.ttr, ds.mtld, ds.yule_k
312
+ (0.8, 14.000000000000004, 600.0)
313
+
314
+ >>> ds.frequency_spectrum
315
+ {1: 7, 3: 1}
316
+
317
+ >>> DiversityStats("La legibilidad de un texto depende de la longitud de sus oraciones y de sus "
318
+ ... "palabras. Las fórmulas clásicas miden esas dos magnitudes y las combinan en "
319
+ ... "un solo número. Ninguna de ellas mide la comprensión: miden la superficie "
320
+ ... "del texto.").windowed("ttr", window_len=10)
321
+ WindowStats(mean=0.875, std=0.1258305739211792, lower=0.6747754774664074, upper=1.0752245225335926, n_windows=4)
322
+ ```
323
+
324
+ More in the [documentation](https://sergeyshk.github.io/esTS/stats/diversity_stats/).
325
+
326
+ </details>
327
+
328
+ ## Development
329
+
330
+ The project uses [uv](https://docs.astral.sh/uv/) for dependency management and [ruff](https://docs.astral.sh/ruff/) for linting and formatting.
331
+
332
+ ```bash
333
+ git clone https://github.com/SergeyShk/esTS.git
334
+ cd esTS
335
+
336
+ make deps # create the environment and install dependencies
337
+ make test # run the tests and docstring examples (doctest)
338
+ make lint # ruff + mypy
339
+ ```
340
+
341
+ Run `make help` for the full list of commands.
342
+
343
+ The documentation is bilingual: English pages are `docs/*.md`, Spanish ones are `docs/*.es.md` next to them ([mkdocs-static-i18n](https://github.com/ultrabug/mkdocs-static-i18n)); when editing a page, update both versions.
344
+
345
+ The installed version is `ests.__version__`. All exceptions inherit `ests.EstsError` and one of the built-in classes (`SourceError` and `ParameterError` - `ValueError`, `SourceTypeError` - `TypeError`, `UnknownStatError` - `KeyError`), so `except ValueError` keeps working. The library prints nothing on its own: its messages go to the `ests` logger (`logging.getLogger("ests")`) and are silent by default.
346
+
347
+ Before submitting changes, install the hooks that run the linters on commit and the tests on push:
348
+
349
+ ```bash
350
+ uv run pre-commit install
351
+ ```
352
+
353
+ ## Contributing
354
+
355
+ Bug reports, ideas and pull requests are welcome - [issues](https://github.com/SergeyShk/esTS/issues) are open. The workflow, the checks to run before submitting a pull request and how to shape the changes are described in [CONTRIBUTING.md](https://github.com/SergeyShk/esTS/blob/master/CONTRIBUTING.md); the rules of conduct are in the [code of conduct](https://github.com/SergeyShk/esTS/blob/master/CODE_OF_CONDUCT.md).
356
+
357
+ <details>
358
+ <summary><b>Project structure</b></summary>
359
+
360
+ <br>
361
+
362
+ * **docs** - project documentation
363
+ * **ests**:
364
+ * basic_stats.py - basic text statistics
365
+ * constants.py - constants of the Spanish language and of the metrics
366
+ * diversity_stats.py - lexical diversity metrics
367
+ * exceptions.py - library exceptions
368
+ * extractors.py - tools for object extraction from a text
369
+ * readability_stats.py - readability metrics
370
+ * syllables.py - syllabification and stress
371
+ * utils.py - helper tools
372
+ * **tests** - tests mirroring the package structure
373
+
374
+ </details>
375
+
376
+ ## Authors
377
+
378
+ * Sergey Shkarin (kouki.sergey@gmail.com)
379
+
380
+ ## License
381
+
382
+ [MIT](https://github.com/SergeyShk/esTS/blob/master/LICENSE.txt)
383
+
384
+ ## Citation
385
+
386
+ Please use the following BibTeX entry for citing **esTS** if you use it in your research or software. Citations are helpful for the continued development and maintenance of this library. The same metadata is in [CITATION.cff](https://github.com/SergeyShk/esTS/blob/master/CITATION.cff) - GitHub shows it under the "Cite this repository" button.
387
+
388
+ ```bibtex
389
+ @software{esTS,
390
+ author = {Sergey Shkarin},
391
+ title = {{esTS, a library for statistics extraction from texts in Spanish}},
392
+ year = 2026,
393
+ url = {https://github.com/SergeyShk/esTS}
394
+ }
395
+ ```