simplibs-extractor-python 0.1.0__py3-none-any.whl

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.
Files changed (71) hide show
  1. simplibs/extractor_python/__init__.py +67 -0
  2. simplibs/extractor_python/actions/PythonOutline.py +23 -0
  3. simplibs/extractor_python/actions/RemovePythonComments.py +22 -0
  4. simplibs/extractor_python/actions/RemovePythonDecorators.py +22 -0
  5. simplibs/extractor_python/actions/RemovePythonDocstrings.py +22 -0
  6. simplibs/extractor_python/actions/RemovePythonImports.py +22 -0
  7. simplibs/extractor_python/actions/__init__.py +45 -0
  8. simplibs/extractor_python/annotations/OnError.py +25 -0
  9. simplibs/extractor_python/annotations/__init__.py +18 -0
  10. simplibs/extractor_python/constants/PYTHON_CONFIG_NAMES.py +27 -0
  11. simplibs/extractor_python/constants/PYTHON_OUTPUT_DIR_NAMES.py +19 -0
  12. simplibs/extractor_python/constants/PYTHON_SUFFIXES.py +17 -0
  13. simplibs/extractor_python/constants/PYTHON_TEST_DIR_NAMES.py +18 -0
  14. simplibs/extractor_python/constants/PYTHON_VENV_DIR_NAMES.py +18 -0
  15. simplibs/extractor_python/constants/__init__.py +26 -0
  16. simplibs/extractor_python/file_rules/__init__.py +62 -0
  17. simplibs/extractor_python/file_rules/atomic/DOT_NAME.py +19 -0
  18. simplibs/extractor_python/file_rules/atomic/INIT_NAME.py +17 -0
  19. simplibs/extractor_python/file_rules/atomic/IN_DUNDER_DIR.py +16 -0
  20. simplibs/extractor_python/file_rules/atomic/MAIN_NAME.py +16 -0
  21. simplibs/extractor_python/file_rules/atomic/OUTPUT_DIRS.py +17 -0
  22. simplibs/extractor_python/file_rules/atomic/VCS_DIRS.py +26 -0
  23. simplibs/extractor_python/file_rules/atomic/VENV_DIRS.py +18 -0
  24. simplibs/extractor_python/file_rules/atomic/__init__.py +30 -0
  25. simplibs/extractor_python/file_rules/python/PYTHON_BASE.py +17 -0
  26. simplibs/extractor_python/file_rules/python/PYTHON_CONFIG.py +18 -0
  27. simplibs/extractor_python/file_rules/python/PYTHON_STRICT_EXCLUDE.py +24 -0
  28. simplibs/extractor_python/file_rules/python/PYTHON_TESTS.py +29 -0
  29. simplibs/extractor_python/file_rules/python/__init__.py +22 -0
  30. simplibs/extractor_python/file_rules/python/build_python_base.py +58 -0
  31. simplibs/extractor_python/logic/__init__.py +32 -0
  32. simplibs/extractor_python/logic/_helpers/SourceOffsets.py +82 -0
  33. simplibs/extractor_python/logic/_helpers/__init__.py +36 -0
  34. simplibs/extractor_python/logic/_helpers/collect_definitions.py +60 -0
  35. simplibs/extractor_python/logic/_helpers/cut_statements.py +126 -0
  36. simplibs/extractor_python/logic/_helpers/describe_source_failure.py +34 -0
  37. simplibs/extractor_python/logic/_helpers/find_decorator_spans.py +107 -0
  38. simplibs/extractor_python/logic/_helpers/find_docstrings.py +46 -0
  39. simplibs/extractor_python/logic/_helpers/find_imports.py +33 -0
  40. simplibs/extractor_python/logic/_helpers/first_doc_line.py +37 -0
  41. simplibs/extractor_python/logic/_helpers/format_type_params.py +29 -0
  42. simplibs/extractor_python/logic/_helpers/guarded_parse.py +64 -0
  43. simplibs/extractor_python/logic/_helpers/outline_node.py +72 -0
  44. simplibs/extractor_python/logic/_helpers/parse_python.py +32 -0
  45. simplibs/extractor_python/logic/_validations/__init__.py +14 -0
  46. simplibs/extractor_python/logic/_validations/raise_python_source_error.py +55 -0
  47. simplibs/extractor_python/logic/python_comment_spans.py +73 -0
  48. simplibs/extractor_python/logic/python_outline.py +63 -0
  49. simplibs/extractor_python/logic/remove_python_comments.py +44 -0
  50. simplibs/extractor_python/logic/remove_python_decorators.py +48 -0
  51. simplibs/extractor_python/logic/remove_python_docstrings.py +50 -0
  52. simplibs/extractor_python/logic/remove_python_imports.py +48 -0
  53. simplibs/extractor_python/plugin/__init__.py +14 -0
  54. simplibs/extractor_python/plugin/register_all.py +45 -0
  55. simplibs/extractor_python/presets/PYTHON_CLEAN.py +29 -0
  56. simplibs/extractor_python/presets/PYTHON_NO_IMPORTS.py +32 -0
  57. simplibs/extractor_python/presets/__init__.py +30 -0
  58. simplibs/extractor_python/profiles/PYTHON_CODE_CLEAN.py +29 -0
  59. simplibs/extractor_python/profiles/PYTHON_CODE_NO_IMPORTS.py +29 -0
  60. simplibs/extractor_python/profiles/PYTHON_DATA_ALL.py +26 -0
  61. simplibs/extractor_python/profiles/PYTHON_OUTLINE.py +30 -0
  62. simplibs/extractor_python/profiles/PYTHON_PROFILES.py +26 -0
  63. simplibs/extractor_python/profiles/PYTHON_SRC_CLEAN.py +30 -0
  64. simplibs/extractor_python/profiles/__init__.py +47 -0
  65. simplibs/extractor_python/py.typed +1 -0
  66. simplibs_extractor_python-0.1.0.dist-info/METADATA +457 -0
  67. simplibs_extractor_python-0.1.0.dist-info/RECORD +71 -0
  68. simplibs_extractor_python-0.1.0.dist-info/WHEEL +5 -0
  69. simplibs_extractor_python-0.1.0.dist-info/entry_points.txt +2 -0
  70. simplibs_extractor_python-0.1.0.dist-info/licenses/LICENSE +21 -0
  71. simplibs_extractor_python-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,48 @@
1
+ from simplibs.validate import validate_call
2
+ # Outers
3
+ from ..annotations import OnError
4
+ # Inners
5
+ from ._helpers import SourceOffsets, cut_statements, find_imports, parse_python
6
+
7
+
8
+ @validate_call
9
+ def remove_python_imports(text: str, *, on_error: OnError = "raise") -> str:
10
+ """Remove the import statements of a Python source, at any depth.
11
+
12
+ Args:
13
+ text: The Python source.
14
+ on_error: `"raise"` for a card when the text cannot be parsed, `"keep"` to return it unchanged.
15
+
16
+ Returns:
17
+ The text without imports. A body left empty gets a `pass`; `import a; x = 1` keeps `x = 1`.
18
+
19
+ Raises:
20
+ ParamError: The text cannot be parsed and `on_error` is `"raise"`.
21
+ """
22
+
23
+ # 1. Parse; a text that could not be read is not touched
24
+ tree = parse_python(text, on_error)
25
+ if tree is None:
26
+ return text
27
+
28
+ # 2. Cut the import statements
29
+ return cut_statements(text, tree, find_imports(tree), SourceOffsets(text))
30
+
31
+
32
+ _DESIGN_NOTES = """
33
+ # remove_python_imports — The Logic Without Its Dependencies
34
+
35
+ ## Purpose
36
+ A step of the profile `python/code-no-imports`.
37
+
38
+ ## Guarantee
39
+ For a text that parses, the syntax tree of the result equals the tree of the
40
+ original without the `Import` and `ImportFrom` statements (and a `Pass` where a
41
+ body would be empty).
42
+
43
+ ## What Is Left Behind
44
+ Names that were imported are still used further down; the reader of the
45
+ output sees code that refers to `Path` or `np` without the line that says
46
+ where they come from. That is what the profile is for: the logic, not the
47
+ wiring.
48
+ """
@@ -0,0 +1,14 @@
1
+ from .register_all import register_all
2
+
3
+
4
+ _DESIGN_NOTES = """
5
+ # plugin — The Meeting Point With the Extractor
6
+
7
+ Plain imports, no `__all__`.
8
+
9
+ ## Internal Components Registry
10
+
11
+ | Component | Type | Description |
12
+ | :------------- | :------- | :---------------------------------------------------- |
13
+ | `register_all` | Function | Registers the profiles; the target of the entry point. |
14
+ """
@@ -0,0 +1,45 @@
1
+ from simplibs.extractor import register_profile
2
+ from simplibs.validate import validate_call
3
+ # Outers
4
+ from ..profiles import PYTHON_PROFILES
5
+
6
+
7
+ @validate_call
8
+ def register_all(*, replace_existing: bool = True) -> list[str]:
9
+ """Register every profile of this library in the registry of the extractor.
10
+
11
+ The extractor calls it, with no arguments, for every installed add-on
12
+ (entry-point group `simplibs.extractor.plugins`).
13
+
14
+ Args:
15
+ replace_existing: Replace a profile that already has the key (the default, so calling it twice changes nothing).
16
+
17
+ Returns:
18
+ The keys of the registered profiles (`"python/code-clean"`...).
19
+
20
+ Raises:
21
+ StateError: A key is taken and `replace_existing` is `False`.
22
+ """
23
+
24
+ # 1. Register each profile
25
+ keys: list[str] = []
26
+ for profile in PYTHON_PROFILES:
27
+ registered = register_profile(profile, replace_existing=replace_existing)
28
+ keys.append(registered.key)
29
+
30
+ return keys
31
+
32
+
33
+ _DESIGN_NOTES = """
34
+ # register_all — What the Entry Point Calls
35
+
36
+ ## Purpose
37
+ `pip install simplibs-extractor-python` is the whole installation: the entry
38
+ point `python = "simplibs.extractor_python:register_all"` makes the extractor
39
+ find this function, and the five profiles appear in `--list-systems`.
40
+
41
+ ## The Rules of an Add-On Function
42
+ It takes no required argument, registers with `replace_existing=True`, only
43
+ registers (no scanning, no network, no printing) and uses only the public API
44
+ of the extractor (`Profile`, `register_profile`).
45
+ """
@@ -0,0 +1,29 @@
1
+ from typing import Final
2
+ from simplibs.text.presets import CLEANUP_WHITESPACE
3
+ # Outers
4
+ from ..actions import RemovePythonComments, RemovePythonDocstrings
5
+
6
+
7
+ PYTHON_CLEAN: Final = (
8
+ RemovePythonComments()
9
+ >> RemovePythonDocstrings()
10
+ >> CLEANUP_WHITESPACE
11
+ )
12
+ """Python without comments and docstrings, whitespace tidied: the imports stay."""
13
+
14
+
15
+ _DESIGN_NOTES = """
16
+ # PYTHON_CLEAN — The Everyday Clean Read
17
+
18
+ ## Purpose
19
+ The steps of `python/code-clean` and `python/src-clean` as one object, built once.
20
+
21
+ ## Order
22
+ Comments first, then docstrings (both find their targets in the original
23
+ structure), whitespace last, to tidy the holes the first two left.
24
+
25
+ ## The Whitespace Step
26
+ `CLEANUP_WHITESPACE` squeezes blank runs to one line; it does not remove them.
27
+ Code stays in paragraphs a person can read. See `PYTHON_NO_IMPORTS` for the
28
+ compact form.
29
+ """
@@ -0,0 +1,32 @@
1
+ from typing import Final
2
+ from simplibs.text.presets import COMPACT
3
+ # Outers
4
+ from ..actions import (
5
+ RemovePythonComments,
6
+ RemovePythonDecorators,
7
+ RemovePythonDocstrings,
8
+ RemovePythonImports,
9
+ )
10
+
11
+
12
+ PYTHON_NO_IMPORTS: Final = (
13
+ RemovePythonComments()
14
+ >> RemovePythonDocstrings()
15
+ >> RemovePythonImports()
16
+ >> RemovePythonDecorators()
17
+ >> COMPACT
18
+ )
19
+ """Python reduced to its logic: no comments, docstrings, imports or decorators, and no blank lines."""
20
+
21
+
22
+ _DESIGN_NOTES = """
23
+ # PYTHON_NO_IMPORTS — The Logic and Nothing Else
24
+
25
+ ## Purpose
26
+ The steps of `python/code-no-imports`.
27
+
28
+ ## Compact, Not Tidy
29
+ `COMPACT` removes every blank line, also those inside multi-line strings. This is
30
+ the shortest form, meant for a reader (or a model) that needs the code and
31
+ not its layout.
32
+ """
@@ -0,0 +1,30 @@
1
+ from .PYTHON_CLEAN import PYTHON_CLEAN
2
+ from .PYTHON_NO_IMPORTS import PYTHON_NO_IMPORTS
3
+
4
+
5
+ __all__ = [
6
+ "PYTHON_CLEAN",
7
+ "PYTHON_NO_IMPORTS",
8
+ ]
9
+
10
+
11
+ _DESIGN_NOTES = """
12
+ # simplibs.extractor_python.presets — Ready-Made Pipeline Steps
13
+
14
+ ## Purpose
15
+ Chains of actions that the profiles use, built once.
16
+
17
+ from simplibs.extractor_python.presets import PYTHON_CLEAN
18
+ steps = PYTHON_CLEAN
19
+
20
+ ## Domain Folder
21
+ `presets/` has its own `__all__` and is not re-exported from the package root.
22
+ It stands to the right of `actions` (it uses them) and to the left of `profiles`.
23
+
24
+ ## Internal Components Registry
25
+
26
+ | Component | Type | Description |
27
+ | :------------------ | :----- | :--------------------------------------------------------- |
28
+ | `PYTHON_CLEAN` | Preset | Python without comments and docstrings, whitespace tidied. |
29
+ | `PYTHON_NO_IMPORTS` | Preset | Python logic only, compact. |
30
+ """
@@ -0,0 +1,29 @@
1
+ from typing import Final
2
+ from simplibs.extractor import Profile, by_suffix
3
+ # Outers
4
+ from ..constants import PYTHON_SUFFIXES
5
+ from ..file_rules import PYTHON_BASE
6
+ from ..presets import PYTHON_CLEAN
7
+
8
+
9
+ PYTHON_CODE_CLEAN: Final[Profile] = Profile(
10
+ system="python",
11
+ name="code-clean",
12
+ description="Python without comments, docstrings and extra blank lines (imports stay)",
13
+ include=PYTHON_BASE,
14
+ steps=by_suffix(PYTHON_CLEAN, PYTHON_SUFFIXES),
15
+ output_name="python_code_clean.md",
16
+ )
17
+ """The profile `python/code-clean`."""
18
+
19
+
20
+ _DESIGN_NOTES = """
21
+ # PYTHON_CODE_CLEAN — `python/code-clean`
22
+
23
+ ## Purpose
24
+ The old `PYTHON_CODE_CLEAN`: the code with its prose taken away.
25
+
26
+ ## Output
27
+ `python_code_clean.md`. A file that is not valid Python makes THAT file an
28
+ `error` in the report; the others are not affected.
29
+ """
@@ -0,0 +1,29 @@
1
+ from typing import Final
2
+ from simplibs.extractor import Profile, by_suffix
3
+ # Outers
4
+ from ..constants import PYTHON_SUFFIXES
5
+ from ..file_rules import PYTHON_BASE
6
+ from ..presets import PYTHON_NO_IMPORTS
7
+
8
+
9
+ PYTHON_CODE_NO_IMPORTS: Final[Profile] = Profile(
10
+ system="python",
11
+ name="code-no-imports",
12
+ description="Pure logic: no imports, decorators, comments, docstrings or blank lines",
13
+ include=PYTHON_BASE,
14
+ steps=by_suffix(PYTHON_NO_IMPORTS, PYTHON_SUFFIXES),
15
+ output_name="python_code_no_imports.md",
16
+ )
17
+ """The profile `python/code-no-imports`."""
18
+
19
+
20
+ _DESIGN_NOTES = """
21
+ # PYTHON_CODE_NO_IMPORTS — `python/code-no-imports`
22
+
23
+ ## Purpose
24
+ The old `PYTHON_CODE_CLEAN_NO_IMPORTS`: what the code does, not what it is
25
+ wired to.
26
+
27
+ ## Output
28
+ `python_code_no_imports.md`.
29
+ """
@@ -0,0 +1,26 @@
1
+ from typing import Final
2
+ from simplibs.extractor import Profile
3
+ # Outers
4
+ from ..file_rules import PYTHON_BASE
5
+
6
+
7
+ PYTHON_DATA_ALL: Final[Profile] = Profile(
8
+ system="python",
9
+ name="data-all",
10
+ description="Every relevant .py file, as it is",
11
+ include=PYTHON_BASE,
12
+ output_name="python_data_all.md",
13
+ )
14
+ """The profile `python/data-all`."""
15
+
16
+
17
+ _DESIGN_NOTES = """
18
+ # PYTHON_DATA_ALL — `python/data-all`
19
+
20
+ ## Purpose
21
+ The old `PYTHON_DATA_ALL`: the files selected by `PYTHON_BASE` and no
22
+ transformation. A file that is not valid Python cannot fail here.
23
+
24
+ ## Output
25
+ `python_data_all.md`.
26
+ """
@@ -0,0 +1,30 @@
1
+ from typing import Final
2
+ from simplibs.extractor import Profile, by_suffix
3
+ # Outers
4
+ from ..actions import PythonOutline
5
+ from ..constants import PYTHON_SUFFIXES
6
+ from ..file_rules import PYTHON_BASE
7
+
8
+
9
+ PYTHON_OUTLINE: Final[Profile] = Profile(
10
+ system="python",
11
+ name="outline",
12
+ description="Overview of classes and functions: signatures without bodies",
13
+ include=PYTHON_BASE,
14
+ steps=by_suffix(PythonOutline(), PYTHON_SUFFIXES),
15
+ output_name="python_outline.md",
16
+ )
17
+ """The profile `python/outline`."""
18
+
19
+
20
+ _DESIGN_NOTES = """
21
+ # PYTHON_OUTLINE — `python/outline`
22
+
23
+ ## Purpose
24
+ New, not in the old code: what a project offers, in a fraction of the size.
25
+ For a reader with a limited window the signatures are most of what is needed
26
+ to ask the right questions.
27
+
28
+ ## Output
29
+ `python_outline.md`; each file is valid Python again.
30
+ """
@@ -0,0 +1,26 @@
1
+ from typing import Final
2
+ from simplibs.extractor import Profile
3
+ # Inners
4
+ from .PYTHON_CODE_CLEAN import PYTHON_CODE_CLEAN
5
+ from .PYTHON_CODE_NO_IMPORTS import PYTHON_CODE_NO_IMPORTS
6
+ from .PYTHON_DATA_ALL import PYTHON_DATA_ALL
7
+ from .PYTHON_OUTLINE import PYTHON_OUTLINE
8
+ from .PYTHON_SRC_CLEAN import PYTHON_SRC_CLEAN
9
+
10
+
11
+ PYTHON_PROFILES: Final[tuple[Profile, ...]] = (
12
+ PYTHON_CODE_CLEAN,
13
+ PYTHON_CODE_NO_IMPORTS,
14
+ PYTHON_DATA_ALL,
15
+ PYTHON_OUTLINE,
16
+ PYTHON_SRC_CLEAN,
17
+ )
18
+ """The profiles of the system `python`."""
19
+
20
+
21
+ _DESIGN_NOTES = """
22
+ # PYTHON_PROFILES — The `python` System
23
+
24
+ ## Purpose
25
+ The profiles of one system in the order the listing commands show them.
26
+ """
@@ -0,0 +1,30 @@
1
+ from typing import Final
2
+ from simplibs.extractor import Profile, by_suffix
3
+ # Outers
4
+ from ..constants import PYTHON_SUFFIXES
5
+ from ..file_rules import PYTHON_BASE, PYTHON_STRICT_EXCLUDE
6
+ from ..presets import PYTHON_CLEAN
7
+
8
+
9
+ PYTHON_SRC_CLEAN: Final[Profile] = Profile(
10
+ system="python",
11
+ name="src-clean",
12
+ description="Like code-clean, without tests, configuration, environments and build folders",
13
+ include=PYTHON_BASE,
14
+ exclude=PYTHON_STRICT_EXCLUDE,
15
+ steps=by_suffix(PYTHON_CLEAN, PYTHON_SUFFIXES),
16
+ output_name="python_src_clean.md",
17
+ )
18
+ """The profile `python/src-clean`."""
19
+
20
+
21
+ _DESIGN_NOTES = """
22
+ # PYTHON_SRC_CLEAN — `python/src-clean`
23
+
24
+ ## Purpose
25
+ The old strict file filter made visible: the old code defined it and no profile
26
+ ever used it. Only what the project does.
27
+
28
+ ## Output
29
+ `python_src_clean.md`.
30
+ """
@@ -0,0 +1,47 @@
1
+ from .PYTHON_CODE_CLEAN import PYTHON_CODE_CLEAN
2
+ from .PYTHON_CODE_NO_IMPORTS import PYTHON_CODE_NO_IMPORTS
3
+ from .PYTHON_DATA_ALL import PYTHON_DATA_ALL
4
+ from .PYTHON_OUTLINE import PYTHON_OUTLINE
5
+ from .PYTHON_PROFILES import PYTHON_PROFILES
6
+ from .PYTHON_SRC_CLEAN import PYTHON_SRC_CLEAN
7
+
8
+
9
+ __all__ = [
10
+ "PYTHON_CODE_CLEAN",
11
+ "PYTHON_CODE_NO_IMPORTS",
12
+ "PYTHON_DATA_ALL",
13
+ "PYTHON_OUTLINE",
14
+ "PYTHON_PROFILES",
15
+ "PYTHON_SRC_CLEAN",
16
+ ]
17
+
18
+
19
+ _DESIGN_NOTES = """
20
+ # simplibs.extractor_python.profiles — The Profiles Themselves
21
+
22
+ ## Purpose
23
+ The five profiles as `Profile` objects of the extractor. Registering them is
24
+ the job of `register_all`; having them as objects lets a program use one
25
+ directly or build its own on top of it.
26
+
27
+ from simplibs.extractor_python.profiles import PYTHON_SRC_CLEAN
28
+ from dataclasses import replace
29
+ mine = replace(PYTHON_SRC_CLEAN, name="mine", output_name="mine.md")
30
+
31
+ ## Domain Folder
32
+ `profiles/` has its own `__all__` and is not re-exported from the package root.
33
+
34
+ ## Internal Components Registry
35
+
36
+ | Component | Type | Description |
37
+ | :----------------------- | :------ | :------------------------------------------------------- |
38
+ | `PYTHON_CODE_CLEAN` | Profile | `python/code-clean`: comments and docstrings removed. |
39
+ | `PYTHON_CODE_NO_IMPORTS` | Profile | `python/code-no-imports`: the logic only. |
40
+ | `PYTHON_DATA_ALL` | Profile | `python/data-all`: every Python file as it is. |
41
+ | `PYTHON_OUTLINE` | Profile | `python/outline`: signatures without bodies. |
42
+ | `PYTHON_PROFILES` | Tuple | All five profiles, in the order the listings show them. |
43
+ | `PYTHON_SRC_CLEAN` | Profile | `python/src-clean`: the project's own logic, cleaned. |
44
+
45
+ ## Layering & Design
46
+ - `by_suffix` (one step for a family of file types) is a tool of `simplibs-extractor`.
47
+ """
@@ -0,0 +1 @@
1
+