simplibs-extractor 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.
- simplibs_extractor-0.1.0/LICENSE +21 -0
- simplibs_extractor-0.1.0/PKG-INFO +605 -0
- simplibs_extractor-0.1.0/README.md +566 -0
- simplibs_extractor-0.1.0/pyproject.toml +90 -0
- simplibs_extractor-0.1.0/setup.cfg +4 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/__init__.py +121 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/__main__.py +12 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/annotations/FileStatus.py +16 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/annotations/OutputFormat.py +25 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/annotations/OverwritePolicy.py +24 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/annotations/StepsSpec.py +26 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/annotations/__init__.py +26 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/annotations/_helpers/__init__.py +15 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/annotations/_helpers/is_output_format.py +36 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/__init__.py +32 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/_helpers/__init__.py +22 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/_helpers/describe_result.py +34 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/_helpers/is_profile_reference.py +34 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/_helpers/print_error.py +25 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/_helpers/profile_options.py +25 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/_helpers/system_options.py +22 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/_validations/__init__.py +22 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/_validations/raise_duplicate_output_error.py +32 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/_validations/raise_list_unknown_system_error.py +34 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/_validations/raise_output_is_file_error.py +30 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/_validations/raise_too_many_positionals_error.py +37 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/_validations/raise_unknown_system_error.py +32 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/build_configs.py +77 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/build_parser.py +68 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/collect_dry_run.py +39 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/collect_profile_keys.py +53 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/collect_source.py +44 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/handle_list_options.py +47 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/normalize_positionals.py +56 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/run_cli.py +101 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/cli/run_init.py +65 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/constants/DEFAULT_MAX_FILE_SIZE.py +18 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/constants/DEFAULT_OUTPUT_NAME.py +14 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/constants/DEFAULT_PROFILE_KEY.py +14 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/constants/DEFAULT_SCRIPT_NAME.py +15 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/constants/GENERATED_MARKER.py +20 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/constants/LANGUAGE_BY_SUFFIX.py +34 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/constants/MARKER_SCAN_LINES.py +18 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/constants/PLUGIN_GROUP.py +20 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/constants/SCRIPT_TEMPLATE.py +32 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/constants/__init__.py +30 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/definitions/Entry.py +26 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/definitions/ExtractionConfig.py +75 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/definitions/ExtractionResult.py +74 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/definitions/FileReport.py +39 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/definitions/Profile.py +95 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/definitions/Resolved.py +28 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/definitions/__init__.py +24 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/definitions/_helpers/__init__.py +16 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/definitions/_helpers/is_key_part.py +31 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/definitions/_helpers/is_suffix_key.py +35 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/definitions/_validations/__init__.py +18 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/definitions/_validations/raise_profile_key_part_error.py +34 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/definitions/_validations/raise_profile_output_name_error.py +33 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/definitions/_validations/raise_profile_steps_key_error.py +33 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/__init__.py +90 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/_common/__init__.py +15 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/_common/describe_failure.py +39 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/_helpers/RunLog.py +57 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/_helpers/__init__.py +18 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/_helpers/build_title.py +28 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/_helpers/process_source.py +59 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/extract.py +119 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/extract_many.py +60 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/failure_result.py +47 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/read/__init__.py +16 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/read/is_generated_file.py +45 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/read/read_source.py +93 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/render/RenderContext.py +34 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/render/__init__.py +31 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/render/_helpers/__init__.py +14 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/render/_helpers/format_tree_lines.py +35 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/render/build_tree.py +36 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/render/register_builtin_renderers.py +26 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/render/render_markdown.py +84 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/render/render_plain.py +57 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/report/__init__.py +16 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/report/_validations/__init__.py +14 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/report/_validations/raise_chars_per_token_error.py +29 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/report/estimate_tokens.py +47 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/report/format_summary.py +67 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/select/__init__.py +24 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/select/_validations/__init__.py +18 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/select/_validations/raise_missing_source_error.py +26 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/select/_validations/raise_source_not_found_error.py +37 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/select/_validations/raise_unknown_parameter_error.py +35 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/select/all_of.py +32 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/select/any_of.py +29 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/select/resolve_config.py +85 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/select/resolve_ignore_names.py +36 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/select/resolve_profile.py +38 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/select/select_sources.py +85 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/transform/__init__.py +16 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/transform/_validations/__init__.py +14 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/transform/_validations/raise_step_result_error.py +42 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/transform/apply_steps.py +57 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/transform/steps_for.py +40 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/write/__init__.py +14 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/write/_validations/__init__.py +16 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/write/_validations/raise_target_exists_error.py +34 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/write/_validations/raise_target_is_dir_error.py +34 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/logic/write/write_output.py +77 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/plugins/__init__.py +14 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/plugins/load_plugins.py +64 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/py.typed +1 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/__init__.py +37 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/_helpers/GENERIC_ALL.py +24 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/_helpers/PROFILE_REGISTRY.py +21 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/_helpers/RENDERER_REGISTRY.py +21 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/_helpers/__init__.py +18 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/_validations/__init__.py +24 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/_validations/raise_missing_system_error.py +33 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/_validations/raise_no_profile_given_error.py +33 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/_validations/raise_profile_exists_error.py +33 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/_validations/raise_profile_not_found_error.py +45 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/_validations/raise_renderer_exists_error.py +30 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/_validations/raise_unknown_renderer_error.py +37 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/expand_profile_keys.py +60 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/get_profile.py +39 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/get_renderer.py +40 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/list_formats.py +20 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/list_profiles.py +32 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/list_systems.py +20 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/register_profile.py +46 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/registry/register_renderer.py +47 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/scripts/__init__.py +18 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/scripts/_helpers/__init__.py +14 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/scripts/_helpers/print_result.py +32 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/scripts/_validations/__init__.py +16 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/scripts/_validations/raise_invalid_output_name_error.py +30 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/scripts/_validations/raise_not_python_script_error.py +30 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/scripts/extract_here.py +93 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/scripts/generate_local_script.py +65 -0
- simplibs_extractor-0.1.0/src/simplibs/extractor/scripts/render_script.py +26 -0
- simplibs_extractor-0.1.0/src/simplibs_extractor.egg-info/PKG-INFO +605 -0
- simplibs_extractor-0.1.0/src/simplibs_extractor.egg-info/SOURCES.txt +145 -0
- simplibs_extractor-0.1.0/src/simplibs_extractor.egg-info/dependency_links.txt +1 -0
- simplibs_extractor-0.1.0/src/simplibs_extractor.egg-info/entry_points.txt +2 -0
- simplibs_extractor-0.1.0/src/simplibs_extractor.egg-info/requires.txt +14 -0
- simplibs_extractor-0.1.0/src/simplibs_extractor.egg-info/top_level.txt +1 -0
- simplibs_extractor-0.1.0/tests/test_architecture.py +133 -0
- simplibs_extractor-0.1.0/tests/test_public_api.py +76 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dalibor Sova (Sudip2708)
|
|
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
|
|
13
|
+
all 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
|
|
21
|
+
THE SOFTWARE.
|
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: simplibs-extractor
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Gathers the text files of a folder into one document: select, read, transform with steps, render as Markdown or plain text, write atomically and report โ as a Python function, a command and a two-line script, with language knowledge brought by add-ons.
|
|
5
|
+
Author-email: "Dalibor Sova (Sudip2708)" <daliborsova@seznam.cz>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/simplibs/simplibs-extractor
|
|
8
|
+
Project-URL: Repository, https://github.com/simplibs/simplibs-extractor
|
|
9
|
+
Project-URL: Issues, https://github.com/simplibs/simplibs-extractor/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/simplibs/simplibs-extractor/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: extractor,code-extractor,project-to-text,files,folder,markdown,llm,context,cli,command-line,profiles,plugins,simplibs,simplibs-extractor,developer-tools
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Classifier: Topic :: Utilities
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: simplibs-exception>=1.1.4
|
|
26
|
+
Requires-Dist: simplibs-validate>=0.3.2
|
|
27
|
+
Requires-Dist: simplibs-path>=0.1.1
|
|
28
|
+
Requires-Dist: simplibs-file>=0.1.0
|
|
29
|
+
Requires-Dist: simplibs-rules>=0.4.0
|
|
30
|
+
Requires-Dist: simplibs-actions>=0.2.2
|
|
31
|
+
Requires-Dist: simplibs-markdown>=0.1.0
|
|
32
|
+
Requires-Dist: simplibs-cli>=0.1.0
|
|
33
|
+
Requires-Dist: simplibs-logger>=0.1.0
|
|
34
|
+
Requires-Dist: simplibs-style>=0.1.0
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: pytest>=9.0; extra == "dev"
|
|
37
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# ๐๏ธ `simplibs-extractor`
|
|
41
|
+
|
|
42
|
+
[](https://pypi.org/project/simplibs-extractor/)
|
|
43
|
+
[](https://www.python.org/downloads/)
|
|
44
|
+
[](https://github.com/simplibs/simplibs-extractor/blob/main/LICENSE)
|
|
45
|
+
[](https://github.com/simplibs/simplibs-extractor/actions)
|
|
46
|
+
|
|
47
|
+
**Many files in, one document out โ and a clear report of what happened to every one of them.**
|
|
48
|
+
|
|
49
|
+
A Python library, a command and a two-line script that gather the **text files of a folder into one
|
|
50
|
+
document**: pick the files, read them, clean their text with steps, render a Markdown (or plain)
|
|
51
|
+
document, write it atomically and tell you what was taken, what was left out and why. The core knows
|
|
52
|
+
**no language**: what a project looks like โ which files, how to clean them โ comes from **profiles**,
|
|
53
|
+
which add-on packages bring (`simplibs-code-extractor` is the first). On its own the extractor takes
|
|
54
|
+
every text file and changes nothing.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
simplibs-extractor generic/all my_project
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
Extraction: generic/all
|
|
62
|
+
source : /home/me/my_project
|
|
63
|
+
target : /home/me/my_project/extraction.md (written)
|
|
64
|
+
files : 4 ok, 1 skipped, 0 errors
|
|
65
|
+
size : 133 B in -> 502 B out (~115 tokens)
|
|
66
|
+
skipped: logo.png (not a text file)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from simplibs.extractor import extract
|
|
71
|
+
|
|
72
|
+
result = extract(source="my_project") # the same extraction from Python
|
|
73
|
+
print(result.success, result.target) # -> True /home/me/my_project/extraction.md
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
> The extractor writes a **report, not a stream of prints**: every run returns an `ExtractionResult`
|
|
77
|
+
> that the command, a script or your own code turns into text, an exit code or a log. The only
|
|
78
|
+
> places that print are the command line and `extract_here` (for people running a script).
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## ๐งญ The Core Philosophy
|
|
83
|
+
|
|
84
|
+
Collecting a project into one file is easy to do badly: the output is read again on the next run, a
|
|
85
|
+
binary or a 50 MB lock file drowns everything, one unreadable file stops the whole job, a dry run
|
|
86
|
+
says "fine" and the real run fails. `simplibs-extractor` is built around those traps:
|
|
87
|
+
|
|
88
|
+
* **Six phases, each one a function.** `Select โ Read โ Transform โ Render โ Write โ Report`. The
|
|
89
|
+
run only wires them together, so each can be understood โ and tested โ alone.
|
|
90
|
+
* **The core knows no language.** Language knowledge lives in **profiles** (rules on paths + steps on
|
|
91
|
+
text) registered by add-ons. A new kind of project is a new profile, not a change in the core.
|
|
92
|
+
* **One bad file never stops a run.** A file that cannot be read or transformed is a line in the
|
|
93
|
+
report with its reason; the run continues. A configuration that cannot run fails **before any file
|
|
94
|
+
is touched**.
|
|
95
|
+
* **`skipped` is not `error`.** A binary file, a file over the size limit, an earlier output โ left
|
|
96
|
+
out on purpose, not a problem. An `error` file was meant to be included and could not be; it makes
|
|
97
|
+
the run unsuccessful.
|
|
98
|
+
* **The output is never its own input.** The target and the files you list are removed from the scan,
|
|
99
|
+
and every output carries a **marker** in its first lines, so even `extraction (1).md` or a backup
|
|
100
|
+
is recognised and skipped on the next run.
|
|
101
|
+
* **A dry run tells the truth.** It makes exactly the decisions a real run makes โ including refusing
|
|
102
|
+
an existing output under the `error` policy โ and writes nothing.
|
|
103
|
+
* **Rules judge the relative path.** A project that merely lies inside a folder called `tests` is not
|
|
104
|
+
dropped as "a test". What a rule can see is the path **inside** the source, so a profile works the
|
|
105
|
+
same wherever the project is.
|
|
106
|
+
* **A config can only narrow.** The `include` you pass is combined with the profile's by AND, the
|
|
107
|
+
`exclude` by OR; a config never widens what a profile selected.
|
|
108
|
+
* **Safe by default.** One megabyte per file, housekeeping folders (`.git`, `node_modules`, virtual
|
|
109
|
+
environments, ...) and half-written drafts are never scanned, the output is written atomically
|
|
110
|
+
(draft and swap), and only the **name** of the source folder โ never its absolute path โ goes into
|
|
111
|
+
the output.
|
|
112
|
+
* **Every error is a card.** A wrong call is a structured card from
|
|
113
|
+
[`simplibs-exception`](https://pypi.org/project/simplibs-exception/) with a name starting with
|
|
114
|
+
`EXTRACTOR_`: what, why, how to fix. The library defines no exception classes of its own.
|
|
115
|
+
* **Layers that only look left.** `annotations` โ `constants` โ `definitions` โ
|
|
116
|
+
`registry` โ `logic` โ `plugins` โ `scripts` โ `cli`.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## ๐ฆ Installation
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
pip install simplibs-extractor
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Requires Python 3.11+. The command is available as `simplibs-extractor` and as
|
|
127
|
+
`python -m simplibs.extractor`. Runtime dependencies, all from the same family:
|
|
128
|
+
[`simplibs-path`](https://pypi.org/project/simplibs-path/) and
|
|
129
|
+
[`simplibs-file`](https://pypi.org/project/simplibs-file/) (scanning, reading, atomic writing),
|
|
130
|
+
[`simplibs-rules`](https://pypi.org/project/simplibs-rules/) and
|
|
131
|
+
[`simplibs-actions`](https://pypi.org/project/simplibs-actions/) (the rules and steps of a profile),
|
|
132
|
+
[`simplibs-markdown`](https://pypi.org/project/simplibs-markdown/) (the Markdown output),
|
|
133
|
+
[`simplibs-cli`](https://pypi.org/project/simplibs-cli/),
|
|
134
|
+
[`simplibs-logger`](https://pypi.org/project/simplibs-logger/) and
|
|
135
|
+
[`simplibs-style`](https://pypi.org/project/simplibs-style/) (the command line),
|
|
136
|
+
[`simplibs-validate`](https://pypi.org/project/simplibs-validate/) and
|
|
137
|
+
[`simplibs-exception`](https://pypi.org/project/simplibs-exception/).
|
|
138
|
+
|
|
139
|
+
A language **add-on** is installed the same way โ `pip install simplibs-code-extractor` โ and its
|
|
140
|
+
profiles show up on their own in `simplibs-extractor --list-systems`. Nothing needs to be imported. From
|
|
141
|
+
Python, call `load_plugins()` once before you look a profile up โ the command does that for you.
|
|
142
|
+
|
|
143
|
+
The text steps used in the examples below come from
|
|
144
|
+
[`simplibs-text`](https://pypi.org/project/simplibs-text/), which is **not** a dependency of the extractor:
|
|
145
|
+
`pip install simplibs-text` when you want them.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## ๐ Quick Start in 60 Seconds
|
|
150
|
+
|
|
151
|
+
### Level 1: The command line
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
simplibs-extractor generic/all my_project # every text file, unchanged -> my_project/extraction.md
|
|
155
|
+
simplibs-extractor generic/all my_project --dry-run # plan and report, write nothing
|
|
156
|
+
simplibs-extractor generic/all my_project -o out --format plain --no-tree
|
|
157
|
+
simplibs-extractor --list-systems # what is installed
|
|
158
|
+
simplibs-extractor --list-profiles python # the profiles of one system (an add-on's)
|
|
159
|
+
simplibs-extractor python code-clean,data-all my_project # two profiles -> two files, one run
|
|
160
|
+
simplibs-extractor # in a terminal: asks for what is missing
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The result of the first command is a Markdown document (the paths are shown as inline code, a
|
|
164
|
+
fenced block per file, the fence always longer than any backticks inside the code):
|
|
165
|
+
|
|
166
|
+
````markdown
|
|
167
|
+
<!-- simplibs-extractor:generated -->
|
|
168
|
+
|
|
169
|
+
# Extraction: my_project
|
|
170
|
+
|
|
171
|
+
Profile: `generic/all`
|
|
172
|
+
|
|
173
|
+
```text
|
|
174
|
+
โโโ src/
|
|
175
|
+
โ โโโ app.py
|
|
176
|
+
โ โโโ config.py
|
|
177
|
+
โโโ tests/
|
|
178
|
+
โ โโโ test_app.py
|
|
179
|
+
โโโ README.md
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## `README.md`
|
|
183
|
+
|
|
184
|
+
```markdown
|
|
185
|
+
# My project
|
|
186
|
+
|
|
187
|
+
A small demo.
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## `src/app.py`
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
import os
|
|
194
|
+
|
|
195
|
+
def main():
|
|
196
|
+
# greet
|
|
197
|
+
print("hi") # inline
|
|
198
|
+
```
|
|
199
|
+
````
|
|
200
|
+
|
|
201
|
+
The command ends with an **exit code**: `0` everything succeeded, `1` some extraction failed or
|
|
202
|
+
selected nothing, `2` the command was refused before anything ran (a typo in a profile, a missing
|
|
203
|
+
source with nobody to ask).
|
|
204
|
+
|
|
205
|
+
### Level 2: From Python
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
from simplibs.extractor import extract, format_summary
|
|
209
|
+
|
|
210
|
+
result = extract(source="my_project", dry_run=True) # everything is a keyword; a typo is refused: extract(sourse=...)
|
|
211
|
+
|
|
212
|
+
result.success # -> True
|
|
213
|
+
[f.relative for f in result.ok_files] # -> ['README.md', 'src/app.py', 'src/config.py', 'tests/test_app.py']
|
|
214
|
+
[(f.relative, f.reason) for f in result.skipped_files] # -> [('logo.png', 'not a text file')]
|
|
215
|
+
result.tokens_estimate # -> 115 a rough guess: characters / 4
|
|
216
|
+
print(format_summary(result)) # the same text the command prints
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
A ready `ExtractionConfig` can be reused with one change โ keywords change a copy of it:
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
from simplibs.extractor import ExtractionConfig, extract
|
|
223
|
+
|
|
224
|
+
config = ExtractionConfig(source="my_project", overwrite="unique", max_file_size=200_000)
|
|
225
|
+
extract(config) # my_project/extraction.md
|
|
226
|
+
extract(config, dry_run=True, add_tree=False) # the same, changed for this call only
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Level 3: Your own profile
|
|
230
|
+
|
|
231
|
+
A **profile** is a name for "which files, how to clean them, what the output is called": rules on the
|
|
232
|
+
relative path plus **steps** that transform each file's text (any `Action` โ the text steps of
|
|
233
|
+
[`simplibs-text`](https://pypi.org/project/simplibs-text/) fit directly).
|
|
234
|
+
|
|
235
|
+
```python
|
|
236
|
+
import re
|
|
237
|
+
from simplibs.extractor import Profile, extract, register_profile
|
|
238
|
+
from simplibs.path.rules import HasSuffix, ParentNameIs
|
|
239
|
+
from simplibs.text.actions import RemoveMatches
|
|
240
|
+
from simplibs.text.presets import COMPACT
|
|
241
|
+
|
|
242
|
+
register_profile(Profile(
|
|
243
|
+
system="python", name="code-clean",
|
|
244
|
+
description="Python sources without comments and blank lines.",
|
|
245
|
+
include=HasSuffix(".py"), # a rule on the path inside the source
|
|
246
|
+
exclude=ParentNameIs("tests"), # a file directly in a folder named tests
|
|
247
|
+
steps=RemoveMatches(pattern=re.compile(r"#.*")) >> COMPACT, # one Action for every file
|
|
248
|
+
output_name="python_clean.md",
|
|
249
|
+
))
|
|
250
|
+
|
|
251
|
+
result = extract(source="my_project", profile="python/code-clean")
|
|
252
|
+
[(f.relative, f.bytes_in, f.bytes_out) for f in result.ok_files]
|
|
253
|
+
# -> [('src/app.py', 62, 38), ('src/config.py', 10, 10)] what the profile saved, file by file
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
`steps` may also be a mapping `suffix -> Action` (`{".py": clean_python, ".md": keep_text, "*": other}`),
|
|
257
|
+
because a step sees only the text, never the path โ a profile that cleans two languages needs two
|
|
258
|
+
pipelines. Rules may be combined with `&`, `|` and `~`; `include` and `exclude` of a single `extract`
|
|
259
|
+
call narrow the profile's.
|
|
260
|
+
|
|
261
|
+
### Level 4: Scripts, batches, formats and add-ons
|
|
262
|
+
|
|
263
|
+
```python
|
|
264
|
+
# extract_here.py โ dropped into a project folder (or: simplibs-extractor init my_project)
|
|
265
|
+
from simplibs.extractor import extract_here
|
|
266
|
+
|
|
267
|
+
extract_here(__file__, profile="python/code-clean") # source = this folder, output next to the script,
|
|
268
|
+
# the script itself is never part of the output
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
```python
|
|
272
|
+
from simplibs.extractor import GENERATED_MARKER, ExtractionConfig, extract, extract_many, register_renderer
|
|
273
|
+
|
|
274
|
+
configs = [ExtractionConfig(source="my_project", profile=key) for key in ("python/code-clean", "generic/all")]
|
|
275
|
+
results = extract_many(configs) # a broken config is a result with `fatal`, the others still run
|
|
276
|
+
|
|
277
|
+
def render_names(entries, context): # a new output format is a function: entries in, text out
|
|
278
|
+
names = "\n".join(entry.relative for entry in entries)
|
|
279
|
+
return f"# {GENERATED_MARKER}\n{names}\n" # the marker keeps the output out of the next run
|
|
280
|
+
|
|
281
|
+
register_renderer("names", render_names)
|
|
282
|
+
extract(source="my_project", format="names", target="my_project/files.txt")
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
An **add-on** announces itself in its own `pyproject.toml`, and the extractor finds it without
|
|
286
|
+
importing it by name:
|
|
287
|
+
|
|
288
|
+
```toml
|
|
289
|
+
[project.entry-points."simplibs.extractor.plugins"]
|
|
290
|
+
code = "simplibs.code_extractor:register_all" # a function with no arguments that registers profiles
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
The command loads add-ons itself; from Python, `load_plugins()` does it (`extract()` never loads add-ons on its own).
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## ๐ฌ The six phases
|
|
298
|
+
|
|
299
|
+
```
|
|
300
|
+
Select โโโบ Read โโโบ Transform โโโบ Render โโโบ Write โโโบ Report
|
|
301
|
+
which text or steps of one atomic, an ExtractionResult,
|
|
302
|
+
files skipped? the profile document policy a summary, an exit code
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
| Phase | What it does | Never does |
|
|
306
|
+
|---------------|-------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------|
|
|
307
|
+
| **Select** | Scans the folder (without ignored names), drops the target and `skip_paths`, applies `include` (AND) and `exclude` (OR) to the **relative** path | reads a file's content |
|
|
308
|
+
| **Read** | Per file, cheapest check first: binary โ generated by us โ too large โ read; reports `skipped` or `error` and never raises for a file | decides which files are taken |
|
|
309
|
+
| **Transform** | Runs the profile's steps on the text (the action of the file's suffix, or the one for all); a step that fails marks **that file** `error` | sees a path, only the text |
|
|
310
|
+
| **Render** | Turns the entries into one text through the renderer of the format; writes the marker, the title and the tree | touches the disk |
|
|
311
|
+
| **Write** | `overwrite`, `unique`, `backup` or `error`; a dry run decides the same and stops; the write itself is atomic | writes in a dry run |
|
|
312
|
+
| **Report** | Builds the `ExtractionResult`: per-file reports, sizes, a token estimate, success | prints (the command and scripts do) |
|
|
313
|
+
|
|
314
|
+
Two kinds of failure, two behaviours. A **configuration that cannot run** (a missing source, an
|
|
315
|
+
unknown profile or format, an unknown parameter) raises a card before any file is read. A **file that
|
|
316
|
+
cannot be used** is a line in the result. A **write that fails** raises, because then there is no
|
|
317
|
+
output at all. An extraction that selected nothing writes nothing and counts as **unsuccessful**: it is
|
|
318
|
+
almost always a wrong filter or a wrong folder, and a file with just a title would hide it.
|
|
319
|
+
|
|
320
|
+
โก๏ธ [README_EXTRACTOR_RUN](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_RUN.md) ยท [SELECT](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_SELECT.md) ยท [READ](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_READ.md) ยท [TRANSFORM](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_TRANSFORM.md) ยท [RENDER](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_RENDER.md) ยท [WRITE](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_WRITE.md) ยท [REPORT](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_REPORT.md)
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## ๐ ๏ธ Architecture & Package Structure
|
|
325
|
+
|
|
326
|
+
```
|
|
327
|
+
src/simplibs/extractor/
|
|
328
|
+
โโโ annotations/ โโโ FileStatus, OutputFormat, OverwritePolicy, StepsSpec
|
|
329
|
+
โโโ constants/ โโโ DEFAULT_*, GENERATED_MARKER, LANGUAGE_BY_SUFFIX, PLUGIN_GROUP, SCRIPT_TEMPLATE, ...
|
|
330
|
+
โโโ definitions/ โโโ Frozen dataclasses: ExtractionConfig, Profile, ExtractionResult, FileReport, Entry
|
|
331
|
+
โโโ registry/ โโโ Profiles and renderers by name: register_*, get_*, list_*, expand_profile_keys
|
|
332
|
+
โโโ logic/ โโโ The six phases and the run
|
|
333
|
+
โ โโโ select/ read/ transform/ render/ write/ report/
|
|
334
|
+
โ โโโ extract.py extract_many.py failure_result.py โโโ The run: the phases put together
|
|
335
|
+
โ โโโ _common/ _helpers/ โโโ Private helpers of the phases and of the run
|
|
336
|
+
โโโ plugins/ โโโ load_plugins: add-ons found through entry points
|
|
337
|
+
โโโ scripts/ โโโ extract_here, generate_local_script
|
|
338
|
+
โโโ cli/ โโโ The command (not imported by the package root)
|
|
339
|
+
โโโ __main__.py โโโ python -m simplibs.extractor
|
|
340
|
+
โโโ py.typed
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Folders named `_validations/`, `_helpers/` and `_common/` are private: they hold the functions that raise the
|
|
344
|
+
library's error cards and the small helpers of the code next to them.
|
|
345
|
+
|
|
346
|
+
Everything a program needs is importable from `simplibs.extractor`. The command line is the one
|
|
347
|
+
exception: `from simplibs.extractor.cli import run_cli` โ so a program that only calls `extract()` does
|
|
348
|
+
not load the prompt and logger libraries it never uses. **Importing the package has two side effects**:
|
|
349
|
+
the profile `generic/all` and the formats `markdown` and `plain` are registered. Nothing else happens
|
|
350
|
+
until a function is called; add-ons are looked up only by `load_plugins()` (which the command calls).
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## ๐ Running an extraction
|
|
355
|
+
|
|
356
|
+
| Function | Description / Parameters |
|
|
357
|
+
|-----------------|-----------------------------------------------------------------------------------------------------------------------------|
|
|
358
|
+
| `extract` | One extraction through all six phases (`config=None`, keyword-only: `logger=None`, and any field of `ExtractionConfig` as a keyword). Returns an `ExtractionResult`. |
|
|
359
|
+
| `extract_many` | Several extractions in a row; a run that cannot start or write appears as a result with `fatal` set and does not stop the others (`configs`, keyword-only: `logger=None`, `stop_on_error=False`). |
|
|
360
|
+
|
|
361
|
+
Progress goes to the `logger` you pass โ a `SimpleLogger`, a standard `logging.Logger` or nothing โ
|
|
362
|
+
and never to the screen.
|
|
363
|
+
|
|
364
|
+
โก๏ธ [README_EXTRACTOR_RUN](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_RUN.md)
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## ๐ `scripts/` โ Two lines in a folder
|
|
369
|
+
|
|
370
|
+
| Function | Description / Parameters |
|
|
371
|
+
|-------------------------|-----------------------------------------------------------------------------------------------------------------------|
|
|
372
|
+
| `extract_here` | Extracts the folder a script lies in into a file next to it; the script itself is left out (`anchor`, `profile=None`, keyword-only: `output_name=None`, `quiet=False`, `logger=None`, any `ExtractionConfig` field). Prints the summary unless `quiet`. |
|
|
373
|
+
| `generate_local_script` | Writes a ready-to-run `extract_here.py` (`path`, `profile=None`, keyword-only: `overwrite=False`); only the profile's **key** is stored. |
|
|
374
|
+
|
|
375
|
+
โก๏ธ [README_EXTRACTOR_SCRIPTS](https://github.com/simplibs/simplibs-extractor/blob/main/docs/README_EXTRACTOR_SCRIPTS.md)
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## ๐งฉ Profiles, registry and add-ons
|
|
380
|
+
|
|
381
|
+
| Function | Description / Parameters |
|
|
382
|
+
|------------------------|-------------------------------------------------------------------------------------------------------------------|
|
|
383
|
+
| `register_profile` | Adds a profile under its `system/name` key and returns it (`profile`, keyword-only: `replace_existing=False`). |
|
|
384
|
+
| `get_profile` | The profile of a key, or a `NotFoundError` card that lists the registered keys (`key`). |
|
|
385
|
+
| `list_profiles` | The registered profiles, sorted by key; a new list (`system=None`). |
|
|
386
|
+
| `list_systems` | The systems that have at least one profile, sorted. |
|
|
387
|
+
| `expand_profile_keys` | Turns what a person typed into full keys: `("python", "a,b")` โ `["python/a", "python/b"]` (`system`, `names`). |
|
|
388
|
+
| `register_renderer` | Adds an output format: a function `(entries, context) -> str` (`name`, `func`, keyword-only: `replace_existing=False`). |
|
|
389
|
+
| `get_renderer` | The renderer of a format, or a card listing the known formats (`name`). |
|
|
390
|
+
| `list_formats` | The registered output formats, sorted. |
|
|
391
|
+
| `load_plugins` | Lets every installed add-on register its profiles; returns `(loaded, failed)` and never lets one add-on stop another (keyword-only: `group`, `entry_points`). |
|
|
392
|
+
|
|
393
|
+
โก๏ธ [README_EXTRACTOR_REGISTRY](https://github.com/simplibs/simplibs-extractor/blob/main/docs/README_EXTRACTOR_REGISTRY.md) ยท [README_EXTRACTOR_PLUGINS](https://github.com/simplibs/simplibs-extractor/blob/main/docs/README_EXTRACTOR_PLUGINS.md) (writing an add-on)
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## ๐ฆ `definitions/` โ Data objects
|
|
398
|
+
|
|
399
|
+
| Class | Description |
|
|
400
|
+
|--------------------|---------------------------------------------------------------------------------------------------------------------------|
|
|
401
|
+
| `ExtractionConfig` | Everything one run needs: `source`, `target`, `profile`, `include`, `exclude`, `ignore_names`, `recursive`, `format`, `overwrite`, `dry_run`, `max_file_size`, `add_tree`, `title`, `skip_paths`. Frozen and validated. |
|
|
402
|
+
| `Profile` | A named set of selection rules and steps: `system`, `name`, `description`, `include`, `exclude`, `steps`, `output_name`, `format`; `key` is `"system/name"`. Frozen and validated when built. |
|
|
403
|
+
| `ExtractionResult` | The outcome of one run: `config`, `profile_key`, `target`, `written`, `dry_run`, `files`, `bytes_in`, `bytes_out`, `tokens_estimate`, `duration`, `fatal`; properties `ok_files`, `skipped_files`, `error_files`, `success`. |
|
|
404
|
+
| `FileReport` | What happened to one file: `path`, `relative`, `status` (`ok`, `skipped`, `error`), `reason`, `bytes_in`, `bytes_out`. |
|
|
405
|
+
| `Entry` | One file ready to be rendered: `relative`, `suffix`, `text`. |
|
|
406
|
+
|
|
407
|
+
`bytes_out` of an `ExtractionResult` is the size of the whole **rendered output** (title, tree and fences
|
|
408
|
+
included); the `bytes_out` of a `FileReport` is the size of that file's text **after the steps** โ so the
|
|
409
|
+
report shows what a profile saves, file by file. `RenderContext`, the other object a renderer receives, is
|
|
410
|
+
described with the [output formats](#-output-formats).
|
|
411
|
+
|
|
412
|
+
โก๏ธ [README_EXTRACTOR_DEFINITIONS](https://github.com/simplibs/simplibs-extractor/blob/main/docs/README_EXTRACTOR_DEFINITIONS.md)
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## ๐จ๏ธ Output formats
|
|
417
|
+
|
|
418
|
+
Two formats are built in, registered through the same door as any later one (the core never branches
|
|
419
|
+
on a format name). Both start with the **marker** `simplibs-extractor:generated` in their first
|
|
420
|
+
lines, which is how an output is recognised โ whatever it is called โ when it lies in a scanned folder.
|
|
421
|
+
**A renderer of your own should write the marker too** (`GENERATED_MARKER`, in its first three lines), or its output would be read back as input on the next run.
|
|
422
|
+
|
|
423
|
+
| Format | What it looks like |
|
|
424
|
+
|------------|-------------------------------------------------------------------------------------------------------------------------------------|
|
|
425
|
+
| `markdown` | A comment with the marker, a title, `Profile: ...`, an optional tree, then `## `path`` and a fenced block per file with the language of its suffix. The default. |
|
|
426
|
+
| `plain` | `# simplibs-extractor:generated`, `# <title>`, `# profile: ...`, an optional `# TREE`, then `# FILE: path` followed by the text โ the layout of the old code extractor. |
|
|
427
|
+
|
|
428
|
+
| Helper | Description |
|
|
429
|
+
|------------------|---------------------------------------------------------------------------------------------------|
|
|
430
|
+
| `RenderContext` | What a renderer receives besides the entries: `title`, `source`, `profile_key`, `add_tree` (exported from the package root, like `Entry`). |
|
|
431
|
+
| `build_tree` | Draws a directory tree from relative paths, folders first (`from simplibs.extractor.logic import build_tree`). |
|
|
432
|
+
| `estimate_tokens` | A **rough** token count: characters / `chars_per_token` (default 4), rounded up. No model name, no tokenizer. |
|
|
433
|
+
| `format_summary` | The readable text of an `ExtractionResult`: counts, sizes, errors first (`result`, keyword-only: `max_listed=10`). |
|
|
434
|
+
|
|
435
|
+
โก๏ธ [README_EXTRACTOR_RENDER](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_RENDER.md) ยท [README_EXTRACTOR_REPORT](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_REPORT.md)
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
## โจ๏ธ The command line
|
|
440
|
+
|
|
441
|
+
```
|
|
442
|
+
simplibs-extractor [SYSTEM] [PROFILES] [SOURCE] [-o FOLDER] [--format NAME] [--overwrite POLICY]
|
|
443
|
+
[--no-tree] [--dry-run] [-q] [-v | -vv] [--no-color]
|
|
444
|
+
simplibs-extractor --list-systems | --list-profiles SYSTEM
|
|
445
|
+
simplibs-extractor init [DIRECTORY] [--profile KEY] [--force]
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
| Option | Meaning |
|
|
449
|
+
|-----------------------|---------------------------------------------------------------------------------------------------------------|
|
|
450
|
+
| `SYSTEM PROFILES` | `python code-clean,data-all`, or full keys: `python/code-clean`, `generic/all,python/data-all`. Several profiles are several runs and several files. |
|
|
451
|
+
| `SOURCE` | The folder to extract from. A first word that is a folder and not a known profile is taken as the source: `simplibs-extractor ./src`. |
|
|
452
|
+
| `-o`, `--output` | The output **folder** (default: the source). The file name always comes from the profile. |
|
|
453
|
+
| `--format` | An output format; the choices are the registered ones. Default: the profile's. |
|
|
454
|
+
| `--overwrite` | `overwrite` (default), `unique`, `backup` or `error`. |
|
|
455
|
+
| `--no-tree` | Leave the directory tree out of the output. |
|
|
456
|
+
| `--dry-run` | Plan and report, write nothing. |
|
|
457
|
+
| `-q`, `-v`, `-vv` | Only errors / more detail / everything; `--no-color` for plain text. |
|
|
458
|
+
| `--list-systems`, `--list-profiles SYSTEM` | Answered from the registry; nothing is extracted. An unknown system is an error, not an empty list. |
|
|
459
|
+
| `init` | Writes a local `extract_here.py` (refuses to replace one without `--force`). |
|
|
460
|
+
|
|
461
|
+
What is missing is asked for in a terminal (the system, then the profiles, then the source; a dry-run
|
|
462
|
+
question only to a person who is already being asked). Without a terminal the same situation is a
|
|
463
|
+
**card** that names the missing argument โ a CI job never hangs. Add-ons that fail to load are
|
|
464
|
+
reported as a warning and do not stop the command.
|
|
465
|
+
|
|
466
|
+
| Exit code | Meaning |
|
|
467
|
+
|-----------|------------------------------------------------------------------------------------------------------|
|
|
468
|
+
| `0` | Everything succeeded. |
|
|
469
|
+
| `1` | Some extraction failed, an `error` file occurred, or nothing was selected. |
|
|
470
|
+
| `2` | The command was refused before anything ran: a mistyped profile, a missing source with nobody to ask, two profiles that would write the same file, an unknown option. |
|
|
471
|
+
|
|
472
|
+
โก๏ธ [README_EXTRACTOR_CLI](https://github.com/simplibs/simplibs-extractor/blob/main/docs/README_EXTRACTOR_CLI.md)
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
## ๐ท๏ธ `annotations/` and `constants/`
|
|
477
|
+
|
|
478
|
+
| Name | Kind | Description |
|
|
479
|
+
|-----------------------|----------------|------------------------------------------------------------------------------------------------------|
|
|
480
|
+
| `FileStatus` | Literal | `"ok"`, `"skipped"` or `"error"`. |
|
|
481
|
+
| `OutputFormat` | Annotated type | The **name** of a format: lowercase, starts with a letter (`"markdown"`, `"json-manifest"`). Whether a renderer exists is checked when the config is resolved. |
|
|
482
|
+
| `OverwritePolicy` | Literal | `"overwrite"`, `"unique"`, `"backup"` or `"error"`. |
|
|
483
|
+
| `StepsSpec` | Type alias | `None`, one `Action`, or a mapping `suffix -> Action` (the key `"*"` is the fallback). |
|
|
484
|
+
| `DEFAULT_PROFILE_KEY` | Constant | `"generic/all"`, the built-in profile: every text file, unchanged. |
|
|
485
|
+
| `GENERATED_MARKER` | Constant | `"simplibs-extractor:generated"`, the text that marks an output. |
|
|
486
|
+
|
|
487
|
+
The other constants (`DEFAULT_MAX_FILE_SIZE` = 1 MB, `DEFAULT_OUTPUT_NAME` = `"extraction.md"`,
|
|
488
|
+
`DEFAULT_SCRIPT_NAME`, `LANGUAGE_BY_SUFFIX`, `MARKER_SCAN_LINES` = 3, `PLUGIN_GROUP`,
|
|
489
|
+
`SCRIPT_TEMPLATE`) are documented in the reference below and importable from `simplibs.extractor.constants`.
|
|
490
|
+
|
|
491
|
+
โก๏ธ [README_EXTRACTOR_ANNOTATIONS](https://github.com/simplibs/simplibs-extractor/blob/main/docs/README_EXTRACTOR_ANNOTATIONS.md) ยท [README_EXTRACTOR_CONSTANTS](https://github.com/simplibs/simplibs-extractor/blob/main/docs/README_EXTRACTOR_CONSTANTS.md)
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
|
|
495
|
+
## โ ๏ธ Exceptions
|
|
496
|
+
|
|
497
|
+
The library defines no exceptions of its own. A wrong call is a structured
|
|
498
|
+
[`simplibs.exception`](https://pypi.org/project/simplibs-exception/) card with a name starting with
|
|
499
|
+
`EXTRACTOR_`; a caller that wants "any error of this library" catches `SimpleError`. Problems of
|
|
500
|
+
**single files** (a read that fails, a step that raises) are not exceptions at all โ they are
|
|
501
|
+
`error` lines in the result.
|
|
502
|
+
|
|
503
|
+
| Error name | Class | Wraps | Raised when |
|
|
504
|
+
|--------------------------------|----------------------|----------------------|------------------------------------------------------------------------------|
|
|
505
|
+
| `EXTRACTOR_CONFIG_INVALID` | `ParamError` | `ValueError` | An unknown config parameter, a missing `source`, an unknown output format, a bad `output_name` or script name, a renderer name that is taken, `chars_per_token <= 0`, unusable command-line arguments |
|
|
506
|
+
| `EXTRACTOR_PROFILE_EXISTS` | `AlreadyExistsError` | `ValueError` | `register_profile` gets a key that is registered and `replace_existing` is `False` |
|
|
507
|
+
| `EXTRACTOR_PROFILE_INVALID` | `ParamError` | `ValueError` | A `Profile` is built with an unusable system, name, `output_name` or `steps` key; `expand_profile_keys` gets a name without a system, or nothing |
|
|
508
|
+
| `EXTRACTOR_PROFILE_NOT_FOUND` | `NotFoundError` | `LookupError` | A profile key is not registered (the card lists the registered ones) |
|
|
509
|
+
| `EXTRACTOR_SOURCE_NOT_FOUND` | `NotFoundError` | `FileNotFoundError` | The source is not an existing directory |
|
|
510
|
+
| `EXTRACTOR_STEP_RESULT_INVALID` | `OperationError` | `TypeError` | A step returned something other than a `str` โ reported against **that file** |
|
|
511
|
+
| `EXTRACTOR_TARGET_EXISTS` | `AlreadyExistsError` | `FileExistsError` | The output exists and the policy is `error` (also in a dry run) |
|
|
512
|
+
| `EXTRACTOR_TARGET_IS_DIR` | `StateError` | `IsADirectoryError` | The output path is an existing directory |
|
|
513
|
+
|
|
514
|
+
A write that fails for other reasons raises the cards of
|
|
515
|
+
[`simplibs-file`](https://pypi.org/project/simplibs-file/) (`AccessError`, `ConversionError`), and a
|
|
516
|
+
missing terminal the card of [`simplibs-cli`](https://pypi.org/project/simplibs-cli/)
|
|
517
|
+
(`CLI_NOT_INTERACTIVE`).
|
|
518
|
+
|
|
519
|
+
What is an exception and what is not:
|
|
520
|
+
|
|
521
|
+
| Situation | How it is reported |
|
|
522
|
+
|---------------------------------------------------------------------------------|----------------------------------------------------------------------|
|
|
523
|
+
| A **wrong call** โ a typo in a parameter, an unknown profile, a missing folder | a card with an `EXTRACTOR_` name, **raised** |
|
|
524
|
+
| A problem of **one file** โ a read that fails, a step that raises | **not raised**: the file is `error` in the result, the run continues |
|
|
525
|
+
| A run that cannot start or cannot write, inside `extract_many` | **not raised**: a result with `fatal` set, the other runs continue |
|
|
526
|
+
| A wrong **type** of a parameter or a field (`overwrite="clobber"`, `format=5`) | a `ValidationError` from `simplibs-validate` |
|
|
527
|
+
|
|
528
|
+
Only the card โ its class and its `EXTRACTOR_` name โ is part of the interface. The functions that raise
|
|
529
|
+
it are private; each lives in a `_validations/` folder next to the code that uses it.
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
## ๐ Documentation
|
|
534
|
+
|
|
535
|
+
The detailed references โ every function and class with its parameters, return value, raised errors, an
|
|
536
|
+
example and a look under the hood:
|
|
537
|
+
|
|
538
|
+
| Reference | What it describes |
|
|
539
|
+
|-----------|-------------------|
|
|
540
|
+
| [ANNOTATIONS](https://github.com/simplibs/simplibs-extractor/blob/main/docs/README_EXTRACTOR_ANNOTATIONS.md) | `FileStatus`, `OutputFormat`, `OverwritePolicy`, `StepsSpec` |
|
|
541
|
+
| [CONSTANTS](https://github.com/simplibs/simplibs-extractor/blob/main/docs/README_EXTRACTOR_CONSTANTS.md) | the fixed values: limits, names, the marker, the script template |
|
|
542
|
+
| [DEFINITIONS](https://github.com/simplibs/simplibs-extractor/blob/main/docs/README_EXTRACTOR_DEFINITIONS.md) | `ExtractionConfig`, `Profile`, `ExtractionResult`, `FileReport`, `Entry` |
|
|
543
|
+
| [REGISTRY](https://github.com/simplibs/simplibs-extractor/blob/main/docs/README_EXTRACTOR_REGISTRY.md) | profiles and output formats by name |
|
|
544
|
+
| [SELECT](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_SELECT.md) ยท [READ](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_READ.md) ยท [TRANSFORM](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_TRANSFORM.md) | phases 1โ3: which files, what is in them, cleaning the text |
|
|
545
|
+
| [RENDER](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_RENDER.md) ยท [WRITE](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_WRITE.md) ยท [REPORT](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_REPORT.md) | phases 4โ6: the document, the disk, the report |
|
|
546
|
+
| [RUN](https://github.com/simplibs/simplibs-extractor/blob/main/docs/logic/README_EXTRACTOR_RUN.md) | `extract`, `extract_many` โ putting the phases together |
|
|
547
|
+
| [PLUGINS](https://github.com/simplibs/simplibs-extractor/blob/main/docs/README_EXTRACTOR_PLUGINS.md) | finding add-ons, and writing one |
|
|
548
|
+
| [SCRIPTS](https://github.com/simplibs/simplibs-extractor/blob/main/docs/README_EXTRACTOR_SCRIPTS.md) | `extract_here`, `generate_local_script` |
|
|
549
|
+
| [CLI](https://github.com/simplibs/simplibs-extractor/blob/main/docs/README_EXTRACTOR_CLI.md) | the command `simplibs-extractor` |
|
|
550
|
+
|
|
551
|
+
---
|
|
552
|
+
|
|
553
|
+
## ๐ Related libraries
|
|
554
|
+
|
|
555
|
+
* **[`simplibs-text`](https://pypi.org/project/simplibs-text/)** โ the text steps (`RemoveMatches`, `COMPACT`, `KeepLineRange`, ...) a profile's `steps` are made of.
|
|
556
|
+
* **`simplibs-code-extractor`** โ the first add-on: profiles for Python and React projects, built on this extractor.
|
|
557
|
+
* **[`simplibs-path`](https://pypi.org/project/simplibs-path/)** โ scanning, normalized paths and the path rules (`HasSuffix`, `ParentNameIs`, ...) behind `include` and `exclude`.
|
|
558
|
+
* **[`simplibs-file`](https://pypi.org/project/simplibs-file/)** โ the atomic write, the backup, the text check and the size.
|
|
559
|
+
* **[`simplibs-rules`](https://pypi.org/project/simplibs-rules/)** and **[`simplibs-actions`](https://pypi.org/project/simplibs-actions/)** โ the `Rule` and `Action` objects a profile is made of.
|
|
560
|
+
* **[`simplibs-markdown`](https://pypi.org/project/simplibs-markdown/)** โ builds the Markdown output.
|
|
561
|
+
* **[`simplibs-cli`](https://pypi.org/project/simplibs-cli/)**, **[`simplibs-logger`](https://pypi.org/project/simplibs-logger/)** and **[`simplibs-style`](https://pypi.org/project/simplibs-style/)** โ the prompts, the logger and the colors of the command.
|
|
562
|
+
* **[`simplibs-validate`](https://pypi.org/project/simplibs-validate/)** and **[`simplibs-exception`](https://pypi.org/project/simplibs-exception/)** โ the validation and the error cards.
|
|
563
|
+
|
|
564
|
+
---
|
|
565
|
+
|
|
566
|
+
## โฏ๏ธ About simplibs
|
|
567
|
+
|
|
568
|
+
All libraries in the **simplibs** (Simple Libraries) ecosystem share a common
|
|
569
|
+
engineering philosophy:
|
|
570
|
+
|
|
571
|
+
* **Dyslexia-friendly:**
|
|
572
|
+
We actively minimize cognitive load. Code is atomized into small, self-contained units,
|
|
573
|
+
files are named directly after the logical task they perform, and explanations describe
|
|
574
|
+
*why* something is designed, not just *what* it is.
|
|
575
|
+
* **Programmer's Zen:**
|
|
576
|
+
Nothing should be missing, and nothing should be superfluous. We value clean execution
|
|
577
|
+
paths and robust, understandable code architectures over rushed, messy feature sets.
|
|
578
|
+
* **Defensive Style:**
|
|
579
|
+
We actively anticipate edge cases and failure modes so that only safe operational paths
|
|
580
|
+
remain. Our code is built to degrade gracefully rather than crash unexpectedly.
|
|
581
|
+
* **Minimalism:**
|
|
582
|
+
Find the most direct path to the goal in as few operational steps as possible without
|
|
583
|
+
taking shortcuts on safety, readability, or completeness.
|
|
584
|
+
* **Code as Craft:**
|
|
585
|
+
Code should be pleasant to look at, readable at a glance, and evoke structural harmony.
|
|
586
|
+
We treat software engineering as a precision trade.
|
|
587
|
+
|
|
588
|
+
---
|
|
589
|
+
|
|
590
|
+
### ๐ค Contributing & Community
|
|
591
|
+
|
|
592
|
+
This is an **open-source project** built with love and care. We strongly believe in
|
|
593
|
+
community collaboration and welcome any feedback, bug reports, or feature ideas!
|
|
594
|
+
|
|
595
|
+
* **Want to contribute?** Feel free to open an Issue or submit a Pull Request.
|
|
596
|
+
* **Want to get in touch?** If you'd like to discuss the project further, collaborate,
|
|
597
|
+
or just say hello, feel free to open a GitHub Issue or start a Discussion.
|
|
598
|
+
|
|
599
|
+
---
|
|
600
|
+
|
|
601
|
+
### ๐ License
|
|
602
|
+
|
|
603
|
+
This library is released under the **MIT License**. Build great things!
|
|
604
|
+
|
|
605
|
+
---
|