textdirectory 0.3.2__tar.gz → 0.4.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.
- textdirectory-0.4.0/.gitignore +106 -0
- textdirectory-0.4.0/AUTHORS.md +9 -0
- textdirectory-0.4.0/CHANGELOG.md +127 -0
- textdirectory-0.4.0/CONTRIBUTING.md +53 -0
- {textdirectory-0.3.2 → textdirectory-0.4.0}/LICENSE +22 -22
- textdirectory-0.4.0/PKG-INFO +262 -0
- textdirectory-0.4.0/README.md +229 -0
- textdirectory-0.4.0/docs/api.rst +36 -0
- textdirectory-0.4.0/docs/changelog.md +5 -0
- textdirectory-0.4.0/docs/conf.py +27 -0
- textdirectory-0.4.0/docs/contributing.md +5 -0
- textdirectory-0.4.0/docs/index.md +25 -0
- textdirectory-0.4.0/docs/installation.md +39 -0
- textdirectory-0.4.0/docs/releasing.md +103 -0
- textdirectory-0.4.0/docs/requirements.txt +4 -0
- textdirectory-0.4.0/docs/usage.md +92 -0
- textdirectory-0.4.0/examples/complex_transformation.py +17 -0
- textdirectory-0.4.0/examples/filter_and_transform.py +16 -0
- textdirectory-0.4.0/examples/repeating_transformation.py +14 -0
- textdirectory-0.4.0/examples/saved_states.py +16 -0
- textdirectory-0.4.0/examples/transform_to_leetspeak.py +13 -0
- textdirectory-0.4.0/pyproject.toml +126 -0
- textdirectory-0.4.0/src/textdirectory/__init__.py +11 -0
- textdirectory-0.4.0/src/textdirectory/__main__.py +6 -0
- textdirectory-0.4.0/src/textdirectory/cli.py +99 -0
- {textdirectory-0.3.2 → textdirectory-0.4.0/src}/textdirectory/crudespellchecker.py +179 -167
- {textdirectory-0.3.2 → textdirectory-0.4.0/src}/textdirectory/data/stopwords/stopwords_en.txt +96 -96
- textdirectory-0.4.0/src/textdirectory/helpers.py +273 -0
- textdirectory-0.4.0/src/textdirectory/py.typed +0 -0
- {textdirectory-0.3.2 → textdirectory-0.4.0/src}/textdirectory/textdirectory.py +607 -487
- textdirectory-0.4.0/src/textdirectory/transformations.py +440 -0
- textdirectory-0.4.0/tests/conftest.py +36 -0
- {textdirectory-0.3.2/textdirectory → textdirectory-0.4.0/tests}/data/testdata/Text_A.txt +9 -9
- {textdirectory-0.3.2/textdirectory → textdirectory-0.4.0/tests}/data/testdata/Text_B.txt +4 -4
- {textdirectory-0.3.2/textdirectory → textdirectory-0.4.0/tests}/data/testdata/Text_C.txt +1 -1
- textdirectory-0.4.0/tests/data/testdata/Text_E.txt +2 -0
- {textdirectory-0.3.2/textdirectory → textdirectory-0.4.0/tests}/data/testdata/level_2/Text_2_A.txt +1 -1
- {textdirectory-0.3.2/textdirectory → textdirectory-0.4.0/tests}/data/testdata/level_2/Text_2_B.txt +1 -1
- {textdirectory-0.3.2/textdirectory → textdirectory-0.4.0/tests}/data/testdata/level_2/Text_2_C.txt +6 -6
- {textdirectory-0.3.2/textdirectory → textdirectory-0.4.0/tests}/data/testdata/level_2/Text_2_D.txt +1 -1
- textdirectory-0.4.0/tests/test_aggregation.py +25 -0
- textdirectory-0.4.0/tests/test_cli.py +117 -0
- textdirectory-0.4.0/tests/test_crudespellchecker.py +71 -0
- textdirectory-0.4.0/tests/test_filters.py +119 -0
- textdirectory-0.4.0/tests/test_general.py +23 -0
- textdirectory-0.4.0/tests/test_helpers.py +129 -0
- textdirectory-0.4.0/tests/test_states.py +42 -0
- textdirectory-0.4.0/tests/test_textdirectory_api.py +106 -0
- textdirectory-0.4.0/tests/test_transformation.py +86 -0
- textdirectory-0.4.0/tests/test_transformations.py +249 -0
- textdirectory-0.3.2/AUTHORS.rst +0 -13
- textdirectory-0.3.2/CONTRIBUTING.rst +0 -128
- textdirectory-0.3.2/HISTORY.rst +0 -81
- textdirectory-0.3.2/MANIFEST.in +0 -15
- textdirectory-0.3.2/PKG-INFO +0 -257
- textdirectory-0.3.2/README.rst +0 -158
- textdirectory-0.3.2/docs/Makefile +0 -20
- textdirectory-0.3.2/docs/_build/html/_static/file.png +0 -0
- textdirectory-0.3.2/docs/_build/html/_static/minus.png +0 -0
- textdirectory-0.3.2/docs/_build/html/_static/plus.png +0 -0
- textdirectory-0.3.2/docs/authors.rst +0 -1
- textdirectory-0.3.2/docs/conf.py +0 -163
- textdirectory-0.3.2/docs/contributing.rst +0 -1
- textdirectory-0.3.2/docs/history.rst +0 -1
- textdirectory-0.3.2/docs/index.rst +0 -20
- textdirectory-0.3.2/docs/installation.rst +0 -51
- textdirectory-0.3.2/docs/make.bat +0 -36
- textdirectory-0.3.2/docs/modules.rst +0 -7
- textdirectory-0.3.2/docs/readme.rst +0 -1
- textdirectory-0.3.2/docs/textdirectory.rst +0 -54
- textdirectory-0.3.2/docs/usage.rst +0 -7
- textdirectory-0.3.2/setup.cfg +0 -29
- textdirectory-0.3.2/setup.py +0 -53
- textdirectory-0.3.2/tests/test_textdirectory.py +0 -191
- textdirectory-0.3.2/textdirectory/__init__.py +0 -10
- textdirectory-0.3.2/textdirectory/cli.py +0 -64
- textdirectory-0.3.2/textdirectory/data/testdata/text_E.txt +0 -2
- textdirectory-0.3.2/textdirectory/helpers.py +0 -182
- textdirectory-0.3.2/textdirectory/transformations.py +0 -302
- textdirectory-0.3.2/textdirectory.egg-info/PKG-INFO +0 -257
- textdirectory-0.3.2/textdirectory.egg-info/SOURCES.txt +0 -51
- textdirectory-0.3.2/textdirectory.egg-info/dependency_links.txt +0 -1
- textdirectory-0.3.2/textdirectory.egg-info/entry_points.txt +0 -3
- textdirectory-0.3.2/textdirectory.egg-info/not-zip-safe +0 -1
- textdirectory-0.3.2/textdirectory.egg-info/requires.txt +0 -8
- textdirectory-0.3.2/textdirectory.egg-info/top_level.txt +0 -1
- {textdirectory-0.3.2 → textdirectory-0.4.0/src}/textdirectory/data/language_models/crudesc_lm_ame.gz.lm +0 -0
- {textdirectory-0.3.2 → textdirectory-0.4.0/src}/textdirectory/data/language_models/crudesc_lm_amehistorical.gz.lm +0 -0
- {textdirectory-0.3.2 → textdirectory-0.4.0/src}/textdirectory/data/language_models/crudesc_lm_en.gz.lm +0 -0
- {textdirectory-0.3.2/textdirectory → textdirectory-0.4.0/tests}/data/testdata/Text_D.txt +0 -0
- {textdirectory-0.3.2/textdirectory → textdirectory-0.4.0/tests}/data/testdata/level_2/Text_2_E.txt +0 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
env/
|
|
12
|
+
build/
|
|
13
|
+
develop-eggs/
|
|
14
|
+
dist/
|
|
15
|
+
downloads/
|
|
16
|
+
eggs/
|
|
17
|
+
.eggs/
|
|
18
|
+
lib/
|
|
19
|
+
lib64/
|
|
20
|
+
parts/
|
|
21
|
+
sdist/
|
|
22
|
+
var/
|
|
23
|
+
wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
|
|
28
|
+
# PyInstaller
|
|
29
|
+
# Usually these files are written by a python script from a template
|
|
30
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
31
|
+
*.manifest
|
|
32
|
+
*.spec
|
|
33
|
+
|
|
34
|
+
# Installer logs
|
|
35
|
+
pip-log.txt
|
|
36
|
+
pip-delete-this-directory.txt
|
|
37
|
+
|
|
38
|
+
# Unit test / coverage reports
|
|
39
|
+
htmlcov/
|
|
40
|
+
.tox/
|
|
41
|
+
.coverage
|
|
42
|
+
.coverage.*
|
|
43
|
+
.cache
|
|
44
|
+
nosetests.xml
|
|
45
|
+
coverage.xml
|
|
46
|
+
*.cover
|
|
47
|
+
.hypothesis/
|
|
48
|
+
.pytest_cache/
|
|
49
|
+
|
|
50
|
+
# Translations
|
|
51
|
+
*.mo
|
|
52
|
+
*.pot
|
|
53
|
+
|
|
54
|
+
# Django stuff:
|
|
55
|
+
*.log
|
|
56
|
+
local_settings.py
|
|
57
|
+
|
|
58
|
+
# Flask stuff:
|
|
59
|
+
instance/
|
|
60
|
+
.webassets-cache
|
|
61
|
+
|
|
62
|
+
# Scrapy stuff:
|
|
63
|
+
.scrapy
|
|
64
|
+
|
|
65
|
+
# Sphinx documentation
|
|
66
|
+
docs/_build/
|
|
67
|
+
|
|
68
|
+
# PyBuilder
|
|
69
|
+
target/
|
|
70
|
+
|
|
71
|
+
# Jupyter Notebook
|
|
72
|
+
.ipynb_checkpoints
|
|
73
|
+
|
|
74
|
+
# pyenv
|
|
75
|
+
.python-version
|
|
76
|
+
|
|
77
|
+
# celery beat schedule file
|
|
78
|
+
celerybeat-schedule
|
|
79
|
+
|
|
80
|
+
# SageMath parsed files
|
|
81
|
+
*.sage.py
|
|
82
|
+
|
|
83
|
+
# dotenv
|
|
84
|
+
.env
|
|
85
|
+
|
|
86
|
+
# virtualenv
|
|
87
|
+
.venv
|
|
88
|
+
venv/
|
|
89
|
+
ENV/
|
|
90
|
+
|
|
91
|
+
# Spyder project settings
|
|
92
|
+
.spyderproject
|
|
93
|
+
.spyproject
|
|
94
|
+
|
|
95
|
+
# Rope project settings
|
|
96
|
+
.ropeproject
|
|
97
|
+
|
|
98
|
+
# mkdocs documentation
|
|
99
|
+
/site
|
|
100
|
+
|
|
101
|
+
# mypy
|
|
102
|
+
.mypy_cache/
|
|
103
|
+
|
|
104
|
+
# PyCharm
|
|
105
|
+
.idea/
|
|
106
|
+
test.txt
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.4.0 (2026-07-26)
|
|
4
|
+
|
|
5
|
+
* modernized the packaging: pyproject.toml + hatchling, src/ layout, uv-based development workflow
|
|
6
|
+
* supported Python versions are now 3.10–3.13
|
|
7
|
+
* made spaCy and psutil optional dependencies (`pip install 'textdirectory[nlp]'` plus `python -m spacy download en_core_web_sm`)
|
|
8
|
+
* dropped the numpy dependency (replaced by the standard library random and statistics modules)
|
|
9
|
+
* spaCy models are now loaded once and cached instead of being reloaded per file and transformation
|
|
10
|
+
* added type hints throughout the package (py.typed)
|
|
11
|
+
* added `--version` and `python -m textdirectory` support to the CLI
|
|
12
|
+
* CLI filter arguments are now coerced to the expected types (filesize, TTR, and similarity filters previously failed from the CLI)
|
|
13
|
+
* CLI errors now exit with a non-zero exit code
|
|
14
|
+
* replaced Travis CI with GitHub Actions; replaced the legacy Read the Docs configuration; rewrote the documentation in Markdown
|
|
15
|
+
* the test corpus is no longer shipped inside the wheel (moved to tests/data/testdata/)
|
|
16
|
+
* fixed destage_transformation, which could never destage anything
|
|
17
|
+
* fixed the CrudeSpellChecker correction cache (wrong cache key) and a crash on tokens without word characters
|
|
18
|
+
* fixed transformation_usas_en_semtag: HTTPS, request timeout, and raising on HTTP errors
|
|
19
|
+
* stage_transformation and run_filters now validate names against the actual registries
|
|
20
|
+
* fixed filter_by_random_sampling turning the aggregation into a numpy array; note that the random sequence differs from previous versions
|
|
21
|
+
* transformation_remove_stopwords now raises for an unknown source or missing stopwords file instead of returning False
|
|
22
|
+
* tabulate_flat_list_of_dicts returns '' for an empty list; type_token_ratio returns 0.0 for empty text
|
|
23
|
+
* aggregate_to_file no longer silently drops unencodable characters when writing
|
|
24
|
+
|
|
25
|
+
## 0.3.4 (2022-09-25)
|
|
26
|
+
|
|
27
|
+
* added transformation_replace_string
|
|
28
|
+
* added filter_by_type_token_ratio
|
|
29
|
+
* added tests for running transformations
|
|
30
|
+
* added contractions fix to transformation_lemmatize
|
|
31
|
+
* added the --disable_tqdm option to the CLI
|
|
32
|
+
* added the ability to output aggregations to the console when using the CLI
|
|
33
|
+
* added (static) coverage badge to the README
|
|
34
|
+
* unified some core approaches (e.g., how filters and transformations are applied; tokenizaton)
|
|
35
|
+
* improved test structure
|
|
36
|
+
* improved documentation
|
|
37
|
+
* fixed transformation_usas_en_semtag
|
|
38
|
+
|
|
39
|
+
## 0.3.3 (2022-09-25)
|
|
40
|
+
|
|
41
|
+
* added filter_by_filenames
|
|
42
|
+
* added filter_by_filename_not_contains
|
|
43
|
+
* added transform_to_files
|
|
44
|
+
* added transformation_eebop4_to_plaintext
|
|
45
|
+
* added transformation_replace_digits
|
|
46
|
+
* added transformation_ftfy
|
|
47
|
+
* added fast and skip_checkpoint options to load_files
|
|
48
|
+
* added __repr__ method to TextDirectory
|
|
49
|
+
* added examples
|
|
50
|
+
* upgraded to spaCy 3
|
|
51
|
+
* improved the test suite
|
|
52
|
+
* fixed some minor bugs
|
|
53
|
+
|
|
54
|
+
## 0.3.2 (2021-01-10)
|
|
55
|
+
|
|
56
|
+
* added transformation_expand_english_contractions
|
|
57
|
+
* fixed some minor bugs
|
|
58
|
+
* added __str__ method to TextDirectory
|
|
59
|
+
* added filename to __str__ output
|
|
60
|
+
* added `get_text` method
|
|
61
|
+
|
|
62
|
+
## 0.3.1 (2020-01-20)
|
|
63
|
+
|
|
64
|
+
* added long_description_content_type to setup.py
|
|
65
|
+
|
|
66
|
+
## 0.3.0 (2020-01-19)
|
|
67
|
+
|
|
68
|
+
* added transformation_remove_weird_tokens
|
|
69
|
+
* added transformation_lemmatizer
|
|
70
|
+
* fixed some minor bugs
|
|
71
|
+
* added a function to revert applied filters
|
|
72
|
+
* added a function that prints the current pipeline
|
|
73
|
+
* added a function that clears all transformations
|
|
74
|
+
* added helper functions to list available filters and transformations
|
|
75
|
+
* fixed a bug in which `tabulate_flat_list_of_dicts` would fail if the dictionary was empty
|
|
76
|
+
* `self.aggregation` does not hold a copy of the files anymore but references to `self.files`
|
|
77
|
+
* transformations relying on spaCy are now estimating a max_length based on available memory
|
|
78
|
+
* TextDirectory objects are now iterable
|
|
79
|
+
|
|
80
|
+
## 0.2.2 (2019-06-13)
|
|
81
|
+
|
|
82
|
+
* changed the data packaging
|
|
83
|
+
|
|
84
|
+
## 0.2.1 (2019-06-13)
|
|
85
|
+
|
|
86
|
+
* added transformation_remove_stopwords
|
|
87
|
+
* added transformation_remove_htmltags
|
|
88
|
+
* fixed some minor bugs
|
|
89
|
+
|
|
90
|
+
## 0.2.0 (2018-05-13)
|
|
91
|
+
|
|
92
|
+
* added transform_to_memory() function
|
|
93
|
+
* added transformation_to_leetspeak() function
|
|
94
|
+
* added transformation_crude_spellchecker
|
|
95
|
+
* added filter_by_max_filesize
|
|
96
|
+
* added filter_by_min_filesize
|
|
97
|
+
* fixed a bug where load_files() would fail if there were no files
|
|
98
|
+
|
|
99
|
+
## 0.1.4 (2018-05-02)
|
|
100
|
+
|
|
101
|
+
* fixed an object mutation problem in the tabulate function
|
|
102
|
+
|
|
103
|
+
## 0.1.3 (2018-04-30)
|
|
104
|
+
|
|
105
|
+
* filter_by_random_sampling now has a "replacement" option
|
|
106
|
+
* changed from tabulate to an embedded function
|
|
107
|
+
* added transformation_remove_non_ascii
|
|
108
|
+
* added transformation_remove_non_alphanumerical
|
|
109
|
+
* added filter_by_similar_documents
|
|
110
|
+
|
|
111
|
+
## 0.1.2 (2018-04-29)
|
|
112
|
+
|
|
113
|
+
* added transformation_postag
|
|
114
|
+
* added transformation_usas_en_semtag
|
|
115
|
+
* added transformation_uppercase
|
|
116
|
+
* added filter_by_filename_contains
|
|
117
|
+
* added parameter support for transformations
|
|
118
|
+
|
|
119
|
+
## 0.1.1 (2018-04-27)
|
|
120
|
+
|
|
121
|
+
* added filter_by_chars_outliers
|
|
122
|
+
* added transformation_remove_nl
|
|
123
|
+
|
|
124
|
+
## 0.1.0 (2018-04-26)
|
|
125
|
+
|
|
126
|
+
* Initial release
|
|
127
|
+
* First release on PyPI.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given.
|
|
4
|
+
|
|
5
|
+
## Ways to Contribute
|
|
6
|
+
|
|
7
|
+
* **Report bugs** at <https://github.com/IngoKl/textdirectory/issues> — please include your operating system,
|
|
8
|
+
Python version, and detailed steps to reproduce.
|
|
9
|
+
* **Fix bugs** or **implement features**: anything tagged `bug` or `enhancement` in the issue tracker is open to
|
|
10
|
+
whoever wants to work on it.
|
|
11
|
+
* **Write documentation**: docstrings, the docs at <https://textdirectory.readthedocs.io>, or blog posts and
|
|
12
|
+
articles elsewhere.
|
|
13
|
+
* **Submit feedback**: the easiest way is to file an issue at <https://github.com/IngoKl/textdirectory/issues>.
|
|
14
|
+
|
|
15
|
+
## Development Setup
|
|
16
|
+
|
|
17
|
+
The project uses [uv](https://docs.astral.sh/uv/) for environments and dependency management.
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
git clone https://github.com/<your-fork>/textdirectory.git
|
|
21
|
+
cd textdirectory
|
|
22
|
+
|
|
23
|
+
# Create the environment with dev tools and the optional NLP dependencies
|
|
24
|
+
uv sync --group dev --extra nlp
|
|
25
|
+
uv pip install https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.8.0/en_core_web_sm-3.8.0-py3-none-any.whl
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Note: if you keep the repository inside a synced folder (e.g. Dropbox), exclude `.venv/` from syncing.
|
|
29
|
+
|
|
30
|
+
## Running Checks
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
uv run pytest # test suite (tests hitting live services are excluded by default)
|
|
34
|
+
uv run pytest -m network # live-service tests (UCREL USAS)
|
|
35
|
+
uv run ruff check src tests
|
|
36
|
+
uv run ruff format --check src tests
|
|
37
|
+
uv run mypy
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Tests that need spaCy and the `en_core_web_sm` model are skipped automatically when they are not installed.
|
|
41
|
+
|
|
42
|
+
## Pull Request Guidelines
|
|
43
|
+
|
|
44
|
+
1. Create a branch for your change and add tests for any new functionality or fixed bug.
|
|
45
|
+
2. Make sure the full check suite above passes locally.
|
|
46
|
+
3. Update the documentation if you add or change functionality (docstrings, README, and the docs pages).
|
|
47
|
+
4. Add an entry to `CHANGELOG.md` under the unreleased version.
|
|
48
|
+
5. The CI runs the tests on Python 3.10–3.13 on Linux and Windows; your change should pass on all of them.
|
|
49
|
+
|
|
50
|
+
## Releasing
|
|
51
|
+
|
|
52
|
+
See the [releasing documentation](https://textdirectory.readthedocs.io/en/latest/releasing.html) for how versions
|
|
53
|
+
are bumped, built, and published to PyPI.
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c)
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
22
|
-
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022, Ingo Kleiber
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: textdirectory
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Aggregate multiple text files into one, with filters and transformations.
|
|
5
|
+
Project-URL: Homepage, https://github.com/IngoKl/textdirectory
|
|
6
|
+
Project-URL: Documentation, https://textdirectory.readthedocs.io
|
|
7
|
+
Project-URL: Repository, https://github.com/IngoKl/textdirectory
|
|
8
|
+
Project-URL: Issues, https://github.com/IngoKl/textdirectory/issues
|
|
9
|
+
Author-email: Ingo Kleiber <ingo@kleiber.me>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: aggregation,corpus,nlp,text,textdirectory
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Natural Language :: English
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Requires-Dist: beautifulsoup4>=4.11
|
|
24
|
+
Requires-Dist: click>=8.1
|
|
25
|
+
Requires-Dist: ftfy>=6.1
|
|
26
|
+
Requires-Dist: lxml>=4.9
|
|
27
|
+
Requires-Dist: requests>=2.28
|
|
28
|
+
Requires-Dist: tqdm>=4.64
|
|
29
|
+
Provides-Extra: nlp
|
|
30
|
+
Requires-Dist: psutil>=5.9; extra == 'nlp'
|
|
31
|
+
Requires-Dist: spacy<4,>=3.8; extra == 'nlp'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# TextDirectory
|
|
35
|
+
|
|
36
|
+
[](https://pypi.org/project/textdirectory/)
|
|
37
|
+
[](https://github.com/IngoKl/textdirectory/actions/workflows/ci.yml)
|
|
38
|
+
[](https://textdirectory.readthedocs.io/en/latest/?badge=latest)
|
|
39
|
+
[](https://pypi.org/project/textdirectory/)
|
|
40
|
+
|
|
41
|
+

|
|
42
|
+
|
|
43
|
+
*TextDirectory* allows you to combine multiple text files into one aggregated file. TextDirectory also supports matching
|
|
44
|
+
files for certain criteria and applying transformations to the aggregated text.
|
|
45
|
+
|
|
46
|
+
*TextDirectory* can be used as a mere tool (via the CLI) and as a Python library.
|
|
47
|
+
|
|
48
|
+
Of course, everything *TextDirectory* does could be achieved in bash or PowerShell. However, there are certain
|
|
49
|
+
use cases (e.g., when used as a library) in which it might be useful.
|
|
50
|
+
|
|
51
|
+
* Free software: MIT license
|
|
52
|
+
* Documentation: <https://textdirectory.readthedocs.io>
|
|
53
|
+
|
|
54
|
+
## Features
|
|
55
|
+
|
|
56
|
+
* Aggregating multiple text files
|
|
57
|
+
* Filtering documents/texts based on various parameters such as length, content, and random sampling
|
|
58
|
+
* Filtering and transforming text files
|
|
59
|
+
* Transforming the aggregated text (e.g., transforming the text to lowercase)
|
|
60
|
+
|
|
61
|
+
| Version | Filters | Transformations |
|
|
62
|
+
|---------|---------|-----------------|
|
|
63
|
+
| 0.1.0 | filter_by_max_chars(n int); filter_by_min_chars(n int); filter_by_max_tokens(n int); filter_by_min_tokens(n int); filter_by_contains(str); filter_by_not_contains(str); filter_by_random_sampling(n int; replace=False) | transformation_lowercase |
|
|
64
|
+
| 0.1.1 | filter_by_chars_outliers(n sigmas int) | transformation_remove_nl |
|
|
65
|
+
| 0.1.2 | filter_by_filename_contains(contains str) | transformation_usas_en_semtag; transformation_uppercase; transformation_postag(spacy_model str) |
|
|
66
|
+
| 0.1.3 | filter_by_similar_documents(reference_file str; threshold float) | transformation_remove_non_ascii; transformation_remove_non_alphanumerical |
|
|
67
|
+
| 0.2.0 | filter_by_max_filesize(max_kb int); filter_by_min_filesize(min_kb int) | transformation_to_leetspeak; transformation_crude_spellchecker(language model str) |
|
|
68
|
+
| 0.2.1 | None | transformation_remove_stopwords(stopwords_source str; stopwords str [en]; spacy_model str; custom_stopwords str); transformation_remove_htmltags |
|
|
69
|
+
| 0.3.0 | None | transformation_remove_weird_tokens(spaCy model; remove_double_space=False); transformation_lemmatize(spaCy model) |
|
|
70
|
+
| 0.3.2 | None | transformation_expand_english_contractions |
|
|
71
|
+
| 0.3.3 | filter_by_filenames(filenames list); filter_by_filename_not_contains(not_contains str) | transformation_eebop4_to_plaintext; transformation_replace_digits(replacement_character str); transformation_ftfy |
|
|
72
|
+
| 0.3.4 | filter_by_type_token_ratio(min_ttr float; max_ttr float) | transformation_replace_string(replace str; replace_with str) |
|
|
73
|
+
| 0.4.0 | None (modernization release) | None (modernization release) |
|
|
74
|
+
|
|
75
|
+
## Installation
|
|
76
|
+
|
|
77
|
+
Install *TextDirectory* via pip:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install textdirectory
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The spaCy-based transformations (`transformation_postag`, `transformation_lemmatize`,
|
|
84
|
+
`transformation_remove_stopwords`, `transformation_remove_weird_tokens`) are optional. To use them, install the
|
|
85
|
+
`nlp` extra and download a spaCy model:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pip install 'textdirectory[nlp]'
|
|
89
|
+
python -m spacy download en_core_web_sm
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Quickstart
|
|
93
|
+
|
|
94
|
+
*TextDirectory*, as exemplified below, works with a two-stage model. After loading in your data (directory) you can,
|
|
95
|
+
by applying *filters*, iteratively select the files you want to process.
|
|
96
|
+
In a second step you can perform transformations on the text before finally aggregating it to either a file or memory.
|
|
97
|
+
|
|
98
|
+

|
|
99
|
+
|
|
100
|
+
### As a Command-Line Tool
|
|
101
|
+
|
|
102
|
+
*TextDirectory* comes equipped with a CLI (`textdirectory`, also available as `python -m textdirectory`).
|
|
103
|
+
|
|
104
|
+
The syntax for both the *filters* and *transformations* works similarly. They are chained by adding slashes (/) and
|
|
105
|
+
parameters are passed via commas (,): `filter_by_min_tokens,5/filter_by_random_sampling,2`.
|
|
106
|
+
|
|
107
|
+
**Example 1: A Very Simple Aggregation**
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
textdirectory --directory testdata --output_file aggregated.txt
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
This will take all files (.txt) in *testdata* and then aggregates the files into a file called *aggregated.txt*.
|
|
114
|
+
|
|
115
|
+
You could also use '*' as a wildcard for filetype if you need to include all files and not just .txt:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
textdirectory --directory testdata --output_file aggregated.txt --filetype *
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Example 2: Applying Filters and Transformations**
|
|
122
|
+
|
|
123
|
+
In this example, we want to filter the files based on their token count, perform a random sampling and finally
|
|
124
|
+
transform all text to lowercase:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
textdirectory --directory testdata --output_file aggregated.txt --filters filter_by_min_tokens,5/filter_by_random_sampling,2 --transformations transformation_lowercase
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
After passing two filters (*filter_by_min_tokens* and *filter_by_random_sampling*) we've applied the
|
|
131
|
+
*transformation_lowercase* transformation.
|
|
132
|
+
|
|
133
|
+
The resulting file will contain the content of two files that each have at least five tokens.
|
|
134
|
+
|
|
135
|
+
The same transformation can also be staged multiple times. For example, we could stage two simple string replacements
|
|
136
|
+
like this:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
textdirectory --directory testdata --output_file aggregated.txt --transformations transformation_replace_string,lorem,x/transformation_replace_string,ipsum,y
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
If the `--output_file` is missing, the CLI will output the aggregated text to the console. In this scenario, there is
|
|
143
|
+
no progress bar visible (can be controlled using `--disable_tqdm True/False`).
|
|
144
|
+
|
|
145
|
+
### As a Python Library
|
|
146
|
+
|
|
147
|
+
In order to demonstrate *TextDirectory* as a Python library, we'll recreate the second example from above:
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
import textdirectory
|
|
151
|
+
|
|
152
|
+
td = textdirectory.TextDirectory(directory='testdata')
|
|
153
|
+
td.load_files(recursive=False, filetype='txt', sort=True)
|
|
154
|
+
td.filter_by_min_tokens(5)
|
|
155
|
+
td.filter_by_random_sampling(2)
|
|
156
|
+
td.stage_transformation(['transformation_lowercase'])
|
|
157
|
+
td.aggregate_to_file('aggregated.txt')
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
If we don't have special requirements, we can also call
|
|
161
|
+
`td = textdirectory.TextDirectory(directory='testdata', autoload=True)` to skip manually calling `load_files`.
|
|
162
|
+
If we wanted to keep working with the actual aggregated text, we could have called `text = td.aggregate_to_memory()`
|
|
163
|
+
instead of `aggregate_to_file`.
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
import textdirectory
|
|
167
|
+
|
|
168
|
+
td = textdirectory.TextDirectory(directory='testdata', autoload=True)
|
|
169
|
+
td.get_text(0)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Sometimes we might want to get the actual text of a given file. This can be achieved as seen above. The `get_text`
|
|
173
|
+
method will return the transformed text if it is available. Otherwise, it will simply read the file and return the
|
|
174
|
+
text.
|
|
175
|
+
|
|
176
|
+
Every applied filter will create a *state* (i.e., a checkpoint). If we want to go back to a previous state, we can
|
|
177
|
+
print all states by calling `td.print_saved_states()`. Previous states can then be loaded by calling
|
|
178
|
+
`td.load_aggregation_state(state=0)`.
|
|
179
|
+
|
|
180
|
+
It's also possible to pass arguments to the individual transformations. In order to do this (at the moment) you have
|
|
181
|
+
to adhere to the correct order of arguments:
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
# def transformation_remove_stopwords(text, stopwords_source='internal', stopwords='en', spacy_model='en_core_web_sm', custom_stopwords=None, *args)
|
|
185
|
+
td.stage_transformation(['transformation_remove_stopwords', 'internal', 'en', 'en_core_web_sm', 'dolor'])
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
In the above example, we are adding additional custom stopwords to the transformer.
|
|
189
|
+
|
|
190
|
+
You also might not always want to aggregate texts into one file in many cases but filter and transform them:
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
import textdirectory
|
|
194
|
+
|
|
195
|
+
td = textdirectory.TextDirectory(directory='input')
|
|
196
|
+
td.load_files()
|
|
197
|
+
|
|
198
|
+
td.filter_by_max_chars(480)
|
|
199
|
+
td.stage_transformation(['transformation_to_leetspeak'])
|
|
200
|
+
|
|
201
|
+
td.transform_to_files('output')
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
In the example above, we are loading all files in `input`. After filtering and transforming, the modified files will
|
|
205
|
+
be written to `output`.
|
|
206
|
+
|
|
207
|
+
In addition, there are a few [simple examples](https://github.com/IngoKl/textdirectory/tree/master/examples) in the
|
|
208
|
+
repository for you to look at.
|
|
209
|
+
|
|
210
|
+
## Special Transformations
|
|
211
|
+
|
|
212
|
+
### transformation_crude_spellchecker
|
|
213
|
+
|
|
214
|
+
This is a very crude spellchecker implemented following Peter Norvig's excellent
|
|
215
|
+
[tutorial](http://norvig.com/spell-correct.html). It's really more of an experiment and not production ready in any
|
|
216
|
+
sense of the word.
|
|
217
|
+
|
|
218
|
+
### transformation_eebop4_to_plaintext
|
|
219
|
+
|
|
220
|
+
This is a highly specific transformation that will extract the plain text from an EEBO-TCP P4 corpus file.
|
|
221
|
+
Both the header as well as all XML tags will be removed during this transformation.
|
|
222
|
+
|
|
223
|
+
### transformation_ftfy
|
|
224
|
+
|
|
225
|
+
This transformation simply applies `ftfy.fix_text` to the text.
|
|
226
|
+
It is highly recommended to use [ftfy](https://pypi.org/project/ftfy/) as a first transformation if you are working
|
|
227
|
+
with messy Unicode text.
|
|
228
|
+
|
|
229
|
+
## Notes for Developers
|
|
230
|
+
|
|
231
|
+
The project uses [uv](https://docs.astral.sh/uv/) for development:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
uv sync --group dev --extra nlp
|
|
235
|
+
uv pip install https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.8.0/en_core_web_sm-3.8.0-py3-none-any.whl
|
|
236
|
+
|
|
237
|
+
uv run pytest # run the test suite (network tests excluded by default)
|
|
238
|
+
uv run pytest -m network # run the tests that hit live external services
|
|
239
|
+
uv run ruff check src tests
|
|
240
|
+
uv run mypy
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full development guide and
|
|
244
|
+
[the releasing documentation](https://textdirectory.readthedocs.io/en/latest/releasing.html) for how releases are
|
|
245
|
+
built and published.
|
|
246
|
+
|
|
247
|
+
## Behavior
|
|
248
|
+
|
|
249
|
+
We are not holding the actual texts in memory. This leads to much more disk read activity (and time inefficiency),
|
|
250
|
+
but saves memory. Of course, this is not the case when using `aggregate_to_memory`.
|
|
251
|
+
|
|
252
|
+
`transformation_usas_en_semtag` relies on the web version of
|
|
253
|
+
[Paul Rayson's USAS Tagger](http://ucrel.lancs.ac.uk/usas/). Don't use this transformation for large amounts of text,
|
|
254
|
+
give credit, and consider using their commercial product [Wmatrix](http://ucrel.lancs.ac.uk/wmatrix/).
|
|
255
|
+
|
|
256
|
+
If you are working with a lot of files, it might be wise to use `load_files(fast=True, skip_checkpoint=True)`.
|
|
257
|
+
This will load files much quicker but skip collecting metadata. This will limit the filters that you can use.
|
|
258
|
+
|
|
259
|
+
## Credits
|
|
260
|
+
|
|
261
|
+
This package was originally based on the
|
|
262
|
+
[audreyr/cookiecutter-pypackage](https://github.com/audreyr/cookiecutter-pypackage) cookiecutter template.
|