handsdown-fork 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 (74) hide show
  1. handsdown/__init__.py +4 -0
  2. handsdown/__main__.py +5 -0
  3. handsdown/ast_parser/__init__.py +28 -0
  4. handsdown/ast_parser/analyzers/__init__.py +1 -0
  5. handsdown/ast_parser/analyzers/base_analyzer.py +29 -0
  6. handsdown/ast_parser/analyzers/class_analyzer.py +176 -0
  7. handsdown/ast_parser/analyzers/expression_analyzer.py +740 -0
  8. handsdown/ast_parser/analyzers/function_analyzer.py +170 -0
  9. handsdown/ast_parser/analyzers/module_analyzer.py +210 -0
  10. handsdown/ast_parser/module_record_list.py +75 -0
  11. handsdown/ast_parser/node_records/__init__.py +1 -0
  12. handsdown/ast_parser/node_records/argument_record.py +107 -0
  13. handsdown/ast_parser/node_records/attribute_record.py +69 -0
  14. handsdown/ast_parser/node_records/class_record.py +136 -0
  15. handsdown/ast_parser/node_records/expression_record.py +60 -0
  16. handsdown/ast_parser/node_records/function_record.py +141 -0
  17. handsdown/ast_parser/node_records/import_record.py +96 -0
  18. handsdown/ast_parser/node_records/module_record.py +298 -0
  19. handsdown/ast_parser/node_records/node_record.py +159 -0
  20. handsdown/ast_parser/node_records/text_record.py +49 -0
  21. handsdown/ast_parser/smart_ast.py +160 -0
  22. handsdown/ast_parser/type_defs.py +24 -0
  23. handsdown/cli_parser.py +294 -0
  24. handsdown/constants.py +22 -0
  25. handsdown/exceptions.py +21 -0
  26. handsdown/generators/__init__.py +0 -0
  27. handsdown/generators/base.py +418 -0
  28. handsdown/generators/material.py +23 -0
  29. handsdown/generators/rtd.py +13 -0
  30. handsdown/jinja_manager.py +60 -0
  31. handsdown/loader.py +159 -0
  32. handsdown/main.py +63 -0
  33. handsdown/md_document.py +327 -0
  34. handsdown/processors/__init__.py +6 -0
  35. handsdown/processors/base.py +308 -0
  36. handsdown/processors/pep257.py +116 -0
  37. handsdown/processors/rst.py +147 -0
  38. handsdown/processors/section.py +43 -0
  39. handsdown/processors/section_block.py +28 -0
  40. handsdown/processors/section_map.py +107 -0
  41. handsdown/processors/smart.py +45 -0
  42. handsdown/py.typed +0 -0
  43. handsdown/templates/common/argument.py.jinja2 +10 -0
  44. handsdown/templates/common/class.md.jinja2 +31 -0
  45. handsdown/templates/common/class_signature.py.jinja2 +15 -0
  46. handsdown/templates/common/docstring.md.jinja2 +8 -0
  47. handsdown/templates/common/function.md.jinja2 +19 -0
  48. handsdown/templates/common/function_signature.py.jinja2 +21 -0
  49. handsdown/templates/common/gh_pages_config.yml.jinja2 +5 -0
  50. handsdown/templates/common/index.md.jinja2 +28 -0
  51. handsdown/templates/common/method.md.jinja2 +21 -0
  52. handsdown/templates/material/mkdocs.yml.jinja2 +41 -0
  53. handsdown/templates/material/module.md.jinja2 +56 -0
  54. handsdown/templates/material/readthedocs.yml.jinja2 +19 -0
  55. handsdown/templates/material/requirements.mkdocs.txt.jinja2 +2 -0
  56. handsdown/templates/readthedocs/mkdocs.yml.jinja2 +9 -0
  57. handsdown/templates/readthedocs/module.md.jinja2 +56 -0
  58. handsdown/templates/readthedocs/readthedocs.yml.jinja2 +15 -0
  59. handsdown/utils/__init__.py +1 -0
  60. handsdown/utils/blackify.py +33 -0
  61. handsdown/utils/docstring_formatter.py +66 -0
  62. handsdown/utils/import_string.py +206 -0
  63. handsdown/utils/indent_trimmer.py +157 -0
  64. handsdown/utils/logger.py +32 -0
  65. handsdown/utils/markdown.py +104 -0
  66. handsdown/utils/path.py +20 -0
  67. handsdown/utils/path_finder.py +204 -0
  68. handsdown/utils/strings.py +74 -0
  69. handsdown_fork-0.1.0.dist-info/METADATA +436 -0
  70. handsdown_fork-0.1.0.dist-info/RECORD +74 -0
  71. handsdown_fork-0.1.0.dist-info/WHEEL +5 -0
  72. handsdown_fork-0.1.0.dist-info/entry_points.txt +2 -0
  73. handsdown_fork-0.1.0.dist-info/licenses/LICENSE +22 -0
  74. handsdown_fork-0.1.0.dist-info/top_level.txt +1 -0
handsdown/__init__.py ADDED
@@ -0,0 +1,4 @@
1
+ """Root of `handsdown` source code."""
2
+
3
+ name = "handsdown"
4
+ __all__ = ["name"]
handsdown/__main__.py ADDED
@@ -0,0 +1,5 @@
1
+ """Main module entrypoint."""
2
+ from handsdown.main import main
3
+
4
+ if __name__ == "__main__":
5
+ main()
@@ -0,0 +1,28 @@
1
+ """
2
+ # AST Parser.
3
+
4
+ Collection of tools for analyzing AST and also rendering it back to a valid Python code.
5
+
6
+ ## Usage
7
+
8
+ Use `handsdown.ast_parser.node_records.ModuleRecord` to parse the source code.
9
+
10
+ ### Examples
11
+
12
+ ```python
13
+ from pathlib import Path
14
+
15
+ from handsdown.utils.import_string import ImportString
16
+ from handsdown.ast_parser.node_records import ModuleRecord
17
+
18
+ source_path = Path("my_module.py")
19
+ import_string = ImportString("my_module")
20
+ module_record = ModuleRecord.create_from_source(source_path, import_string)
21
+ module_record.build_children() # generate records for imports, classes, attributes
22
+ and function in module
23
+
24
+ function_record = module_record.function_records[0] # get the first function in module
25
+ print(function_record.render(allow_multiline=True)) # print function definition
26
+ print(function_record.return_type_hint.render()) # print function return type annotation
27
+ ```
28
+ """
@@ -0,0 +1 @@
1
+ """AST Analyzers."""
@@ -0,0 +1,29 @@
1
+ """Base AST analyzer."""
2
+
3
+ import handsdown.ast_parser.smart_ast as ast
4
+
5
+
6
+ class BaseAnalyzer(ast.NodeVisitor):
7
+ """
8
+ Base AST analyzer.
9
+
10
+ Has lists for all objects for different analyzers.
11
+ """
12
+
13
+ def __init__(self) -> None:
14
+ self.related_names: list[str] = []
15
+
16
+ def get_docstring(self, node: ast.AST) -> str:
17
+ """
18
+ Get docstring from node.
19
+
20
+ Arguments:
21
+ node -- AST node.
22
+
23
+ Returns:
24
+ Docstring.
25
+
26
+ """
27
+ if isinstance(node, (ast.AsyncFunctionDef, ast.FunctionDef, ast.ClassDef, ast.Module)):
28
+ return ast.get_docstring(node, clean=False) or ""
29
+ return ""
@@ -0,0 +1,176 @@
1
+ """AST analyzer for `ast.ClassDef` records."""
2
+ from typing import Union
3
+
4
+ import handsdown.ast_parser.smart_ast as ast
5
+ from handsdown.ast_parser.analyzers.base_analyzer import BaseAnalyzer
6
+ from handsdown.ast_parser.type_defs import ASTFunctionDef
7
+
8
+
9
+ class ClassAnalyzer(BaseAnalyzer):
10
+ """AST analyzer for `ast.ClassDef` records."""
11
+
12
+ def __init__(self) -> None:
13
+ super().__init__()
14
+ self.base_nodes: list[ast.expr] = []
15
+ self.decorator_nodes: list[ast.expr] = []
16
+ self.method_nodes: list[ASTFunctionDef] = []
17
+ self.attribute_nodes: list[Union[ast.Assign, ast.AnnAssign]] = []
18
+
19
+ def visit_ClassDef(self, node: ast.ClassDef) -> None:
20
+ """
21
+ Entrypoint for the analyzer.
22
+
23
+ Adds new `ast.expr` entry to `decorator_nodes` for each node
24
+ from `node.decorator_list`.
25
+ Adds new `ast.expr` entry to `base_nodes` for each node
26
+ from `node.bases`.
27
+ Visits each node from `node.body` list to parse methods.
28
+
29
+ Examples::
30
+
31
+ def my_func():
32
+ pass
33
+
34
+ Arguments:
35
+ node -- AST node.
36
+
37
+ """
38
+ for decorator_node in node.decorator_list:
39
+ self.decorator_nodes.append(decorator_node)
40
+ for base_node in node.bases:
41
+ self.base_nodes.append(base_node)
42
+ for element in node.body:
43
+ self.visit(element)
44
+
45
+ def _visit_FunctionDef(self, node: ASTFunctionDef) -> None:
46
+ name = node.name
47
+
48
+ docstring = self.get_docstring(node)
49
+
50
+ # skip private methods with no docstrings
51
+ if name.startswith("_") and not name.startswith("__") and not docstring:
52
+ return
53
+
54
+ # skip magic methods with no docstrings
55
+ if name.startswith("__") and name != "__init__" and not docstring:
56
+ return
57
+
58
+ self.method_nodes.append(node)
59
+
60
+ def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
61
+ """
62
+ Parse info about class method statements.
63
+
64
+ Adds new `FunctionRecord` entry to `method_records`.
65
+
66
+ Examples:
67
+ ```python
68
+ class MyClass:
69
+ def my_method(self, arg):
70
+ return arg
71
+ ```
72
+
73
+ Arguments:
74
+ node -- AST node.
75
+
76
+ """
77
+ self._visit_FunctionDef(node)
78
+
79
+ def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None:
80
+ """
81
+ Parse info about class asynchronous method statements.
82
+
83
+ Adds new `FunctionRecord` entry to `method_records`.
84
+
85
+ Examples:
86
+ ```python
87
+ class MyClass:
88
+ async def my_method(self, arg):
89
+ return await arg
90
+ ```
91
+
92
+ Arguments:
93
+ node -- AST node.
94
+
95
+ """
96
+ self._visit_FunctionDef(node)
97
+
98
+ def visit_Assign(self, node: ast.Assign) -> None:
99
+ """
100
+ Parse info about class attribute statements.
101
+
102
+ Adds new `ast.Assign` entry to `attribute_nodes`.
103
+ Skips assignments to anything pther that a new variable.
104
+ Skips multiple assignments.
105
+ Skips assignments with names starting with `_`.
106
+
107
+ Examples:
108
+ ```python
109
+ class MyClass:
110
+ MY_MODULE_ATTR = "value"
111
+ my_attr = "value"
112
+
113
+ # these entries are skipped
114
+ _MY_MODULE_ATTR = "value"
115
+ multi_attr_1, multi_attr_2 = [1, 2]
116
+ my_object.name = "value"
117
+ ```
118
+
119
+ Arguments:
120
+ node -- AST node.
121
+
122
+ """
123
+ # skip multiple assignments
124
+ if len(node.targets) != 1:
125
+ return
126
+
127
+ # skip complex assignments
128
+ if not isinstance(node.targets[0], ast.Name):
129
+ return
130
+
131
+ name = node.targets[0].id
132
+
133
+ # skip private attributes
134
+ if name.startswith("_"):
135
+ return
136
+
137
+ self.attribute_nodes.append(node)
138
+
139
+ def visit_AnnAssign(self, node: ast.AnnAssign) -> None:
140
+ """
141
+ Parse info about class annotated attribute statements.
142
+
143
+ Adds new `ast.AnnAssign` entry to `attribute_nodes`.
144
+ Skips assignments with names starting with `_`.
145
+
146
+ Examples:
147
+ ```python
148
+ class MyClass:
149
+ my_attr: int
150
+ my_value: int = 5
151
+ ```
152
+
153
+ Arguments:
154
+ node -- AST node.
155
+
156
+ """
157
+ # skip complex assignments
158
+ if not isinstance(node.target, ast.Name):
159
+ return
160
+
161
+ name = node.target.id
162
+
163
+ # skip private attributes
164
+ if name.startswith("_"):
165
+ return
166
+
167
+ self.attribute_nodes.append(node)
168
+
169
+ def generic_visit(self, node: ast.AST) -> None:
170
+ """
171
+ Do nothing for unknown `ast.AST` nodes.
172
+
173
+ Arguments:
174
+ node -- AST node.
175
+
176
+ """