docstring-generator-ext 1.0.3a5__tar.gz → 2.0.1__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.
Files changed (31) hide show
  1. {docstring_generator_ext-1.0.3a5 → docstring_generator_ext-2.0.1}/MANIFEST.in +1 -2
  2. {docstring_generator_ext-1.0.3a5 → docstring_generator_ext-2.0.1}/PKG-INFO +50 -1
  3. {docstring_generator_ext-1.0.3a5 → docstring_generator_ext-2.0.1}/README.md +49 -0
  4. {docstring_generator_ext-1.0.3a5 → docstring_generator_ext-2.0.1}/docstring_generator_ext.egg-info/PKG-INFO +50 -1
  5. docstring_generator_ext-2.0.1/docstring_generator_ext.egg-info/SOURCES.txt +25 -0
  6. {docstring_generator_ext-1.0.3a5 → docstring_generator_ext-2.0.1}/pyproject.toml +1 -1
  7. docstring_generator_ext-2.0.1/setup.py +59 -0
  8. docstring_generator_ext-2.0.1/src/FunctionFormat.cpp +177 -0
  9. docstring_generator_ext-2.0.1/src/FunctionFormat.hpp +72 -0
  10. docstring_generator_ext-2.0.1/src/GoogleDocstring.cpp +121 -0
  11. docstring_generator_ext-2.0.1/src/GoogleDocstring.hpp +14 -0
  12. docstring_generator_ext-2.0.1/src/IDocstringFormat.cpp +32 -0
  13. docstring_generator_ext-2.0.1/src/IDocstringFormat.hpp +26 -0
  14. docstring_generator_ext-2.0.1/src/NumpyDocstring.cpp +123 -0
  15. docstring_generator_ext-2.0.1/src/NumpyDocstring.hpp +12 -0
  16. docstring_generator_ext-2.0.1/src/ReStructuredDocstring.cpp +86 -0
  17. docstring_generator_ext-2.0.1/src/ReStructuredDocstring.hpp +21 -0
  18. docstring_generator_ext-2.0.1/src/docComparator.cpp +93 -0
  19. docstring_generator_ext-2.0.1/src/docComparator.hpp +15 -0
  20. docstring_generator_ext-2.0.1/src/docstringFormat.cpp +206 -0
  21. docstring_generator_ext-2.0.1/src/docstringFormat.hpp +24 -0
  22. docstring_generator_ext-2.0.1/src/parser.cpp +487 -0
  23. docstring_generator_ext-2.0.1/src/parser.hpp +54 -0
  24. docstring_generator_ext-1.0.3a5/docstring_generator_ext.egg-info/SOURCES.txt +0 -11
  25. docstring_generator_ext-1.0.3a5/setup.py +0 -21
  26. docstring_generator_ext-1.0.3a5/src/docstringFormat.cpp +0 -1111
  27. docstring_generator_ext-1.0.3a5/src/docstringFormat.hpp +0 -115
  28. {docstring_generator_ext-1.0.3a5 → docstring_generator_ext-2.0.1}/docstring_generator_ext.egg-info/dependency_links.txt +0 -0
  29. {docstring_generator_ext-1.0.3a5 → docstring_generator_ext-2.0.1}/docstring_generator_ext.egg-info/requires.txt +0 -0
  30. {docstring_generator_ext-1.0.3a5 → docstring_generator_ext-2.0.1}/docstring_generator_ext.egg-info/top_level.txt +0 -0
  31. {docstring_generator_ext-1.0.3a5 → docstring_generator_ext-2.0.1}/setup.cfg +0 -0
@@ -2,8 +2,7 @@
2
2
  include README.md
3
3
  include pyproject.toml
4
4
  include setup.py
5
- include src/docstringFormat.cpp
6
- include src/docstringFormat.hpp
5
+ recursive-include src *.cpp *.hpp
7
6
 
8
7
  # What to exclude
9
8
  prune src/cmake-build-debug
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docstring_generator_ext
3
- Version: 1.0.3a5
3
+ Version: 2.0.1
4
4
  Summary: Generate Docstrings with type-hint information.
5
5
  Author-email: FelixTheC <fberndt87@gmail.com>
6
6
  Classifier: Environment :: Console
@@ -81,6 +81,32 @@ style = docstring_generator_ext.DocstringFormatStyle.GOOGLE
81
81
  docstring_generator_ext.parse_file(file_path, style)
82
82
  ```
83
83
 
84
+ You can also audit an existing file to see how well its functions are documented, without making any changes:
85
+
86
+ ```python
87
+ import docstring_generator_ext
88
+
89
+ # Path to the Python file you want to audit
90
+ file_path = "path/to/your_script.py"
91
+
92
+ # Returns a dict with docstring coverage statistics
93
+ result = docstring_generator_ext.check_docstring(file_path)
94
+
95
+ print(f"Functions checked : {result['num_functions_checked']}")
96
+ print(f"Complete docstrings: {result['complete_docstrings']}")
97
+ print(f"Partial docstrings : {result['partial_docstrings']}")
98
+ print(f"No docstrings : {result['no_docstrings']}")
99
+ ```
100
+
101
+ The returned dictionary always contains four keys:
102
+
103
+ | Key | Description |
104
+ |-----|-------------|
105
+ | `num_functions_checked` | Total number of functions/methods found in the file |
106
+ | `complete_docstrings` | Functions whose docstring fully matches the signature |
107
+ | `partial_docstrings` | Functions with an incomplete or outdated docstring |
108
+ | `no_docstrings` | Functions with no docstring at all |
109
+
84
110
  ### Docstring Styles
85
111
 
86
112
  The extension provides an enum `DocstringFormatStyle` to choose the desired output:
@@ -89,6 +115,28 @@ The extension provides an enum `DocstringFormatStyle` to choose the desired outp
89
115
  - `docstring_generator_ext.DocstringFormatStyle.GOOGLE`
90
116
  - `docstring_generator_ext.DocstringFormatStyle.NUMPY`
91
117
 
118
+ ## C++20
119
+
120
+ The core of this extension is written in **C++20** to take full advantage of the modern standard's best algorithms and features:
121
+
122
+ - **`std::format`**: Used for clean, type-safe string formatting throughout the docstring generation logic.
123
+ - **Ranges & views**: C++20 ranges enable expressive, composable data transformations without raw loops.
124
+ - **Concepts**: Improve template code clarity and provide better compiler error messages.
125
+ - **`std::span`**: Provides safe, bounds-checked views over contiguous data without ownership overhead.
126
+
127
+ ### Compiler Requirements
128
+
129
+ Building from source requires a C++ compiler with full C++20 support:
130
+
131
+ | Platform | Minimum version |
132
+ |----------|-------------------------|
133
+ | Linux | GCC 11+ / Clang 14+ |
134
+ | macOS | Apple Clang 15+ / GCC 13+ (via Homebrew) |
135
+ | Windows | MSVC 2022 (19.30+) |
136
+
137
+ Pre-built wheels on [PyPI](https://pypi.org/project/docstring_generator_ext/) are compiled with C++20 enabled and require no special toolchain on the user's side.
138
+
139
+
92
140
  ## Authors
93
141
 
94
142
  - **FelixTheC**
@@ -97,3 +145,4 @@ The extension provides an enum `DocstringFormatStyle` to choose the desired outp
97
145
 
98
146
  This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.
99
147
 
148
+
@@ -67,6 +67,32 @@ style = docstring_generator_ext.DocstringFormatStyle.GOOGLE
67
67
  docstring_generator_ext.parse_file(file_path, style)
68
68
  ```
69
69
 
70
+ You can also audit an existing file to see how well its functions are documented, without making any changes:
71
+
72
+ ```python
73
+ import docstring_generator_ext
74
+
75
+ # Path to the Python file you want to audit
76
+ file_path = "path/to/your_script.py"
77
+
78
+ # Returns a dict with docstring coverage statistics
79
+ result = docstring_generator_ext.check_docstring(file_path)
80
+
81
+ print(f"Functions checked : {result['num_functions_checked']}")
82
+ print(f"Complete docstrings: {result['complete_docstrings']}")
83
+ print(f"Partial docstrings : {result['partial_docstrings']}")
84
+ print(f"No docstrings : {result['no_docstrings']}")
85
+ ```
86
+
87
+ The returned dictionary always contains four keys:
88
+
89
+ | Key | Description |
90
+ |-----|-------------|
91
+ | `num_functions_checked` | Total number of functions/methods found in the file |
92
+ | `complete_docstrings` | Functions whose docstring fully matches the signature |
93
+ | `partial_docstrings` | Functions with an incomplete or outdated docstring |
94
+ | `no_docstrings` | Functions with no docstring at all |
95
+
70
96
  ### Docstring Styles
71
97
 
72
98
  The extension provides an enum `DocstringFormatStyle` to choose the desired output:
@@ -75,6 +101,28 @@ The extension provides an enum `DocstringFormatStyle` to choose the desired outp
75
101
  - `docstring_generator_ext.DocstringFormatStyle.GOOGLE`
76
102
  - `docstring_generator_ext.DocstringFormatStyle.NUMPY`
77
103
 
104
+ ## C++20
105
+
106
+ The core of this extension is written in **C++20** to take full advantage of the modern standard's best algorithms and features:
107
+
108
+ - **`std::format`**: Used for clean, type-safe string formatting throughout the docstring generation logic.
109
+ - **Ranges & views**: C++20 ranges enable expressive, composable data transformations without raw loops.
110
+ - **Concepts**: Improve template code clarity and provide better compiler error messages.
111
+ - **`std::span`**: Provides safe, bounds-checked views over contiguous data without ownership overhead.
112
+
113
+ ### Compiler Requirements
114
+
115
+ Building from source requires a C++ compiler with full C++20 support:
116
+
117
+ | Platform | Minimum version |
118
+ |----------|-------------------------|
119
+ | Linux | GCC 11+ / Clang 14+ |
120
+ | macOS | Apple Clang 15+ / GCC 13+ (via Homebrew) |
121
+ | Windows | MSVC 2022 (19.30+) |
122
+
123
+ Pre-built wheels on [PyPI](https://pypi.org/project/docstring_generator_ext/) are compiled with C++20 enabled and require no special toolchain on the user's side.
124
+
125
+
78
126
  ## Authors
79
127
 
80
128
  - **FelixTheC**
@@ -83,3 +131,4 @@ The extension provides an enum `DocstringFormatStyle` to choose the desired outp
83
131
 
84
132
  This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.
85
133
 
134
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docstring_generator_ext
3
- Version: 1.0.3a5
3
+ Version: 2.0.1
4
4
  Summary: Generate Docstrings with type-hint information.
5
5
  Author-email: FelixTheC <fberndt87@gmail.com>
6
6
  Classifier: Environment :: Console
@@ -81,6 +81,32 @@ style = docstring_generator_ext.DocstringFormatStyle.GOOGLE
81
81
  docstring_generator_ext.parse_file(file_path, style)
82
82
  ```
83
83
 
84
+ You can also audit an existing file to see how well its functions are documented, without making any changes:
85
+
86
+ ```python
87
+ import docstring_generator_ext
88
+
89
+ # Path to the Python file you want to audit
90
+ file_path = "path/to/your_script.py"
91
+
92
+ # Returns a dict with docstring coverage statistics
93
+ result = docstring_generator_ext.check_docstring(file_path)
94
+
95
+ print(f"Functions checked : {result['num_functions_checked']}")
96
+ print(f"Complete docstrings: {result['complete_docstrings']}")
97
+ print(f"Partial docstrings : {result['partial_docstrings']}")
98
+ print(f"No docstrings : {result['no_docstrings']}")
99
+ ```
100
+
101
+ The returned dictionary always contains four keys:
102
+
103
+ | Key | Description |
104
+ |-----|-------------|
105
+ | `num_functions_checked` | Total number of functions/methods found in the file |
106
+ | `complete_docstrings` | Functions whose docstring fully matches the signature |
107
+ | `partial_docstrings` | Functions with an incomplete or outdated docstring |
108
+ | `no_docstrings` | Functions with no docstring at all |
109
+
84
110
  ### Docstring Styles
85
111
 
86
112
  The extension provides an enum `DocstringFormatStyle` to choose the desired output:
@@ -89,6 +115,28 @@ The extension provides an enum `DocstringFormatStyle` to choose the desired outp
89
115
  - `docstring_generator_ext.DocstringFormatStyle.GOOGLE`
90
116
  - `docstring_generator_ext.DocstringFormatStyle.NUMPY`
91
117
 
118
+ ## C++20
119
+
120
+ The core of this extension is written in **C++20** to take full advantage of the modern standard's best algorithms and features:
121
+
122
+ - **`std::format`**: Used for clean, type-safe string formatting throughout the docstring generation logic.
123
+ - **Ranges & views**: C++20 ranges enable expressive, composable data transformations without raw loops.
124
+ - **Concepts**: Improve template code clarity and provide better compiler error messages.
125
+ - **`std::span`**: Provides safe, bounds-checked views over contiguous data without ownership overhead.
126
+
127
+ ### Compiler Requirements
128
+
129
+ Building from source requires a C++ compiler with full C++20 support:
130
+
131
+ | Platform | Minimum version |
132
+ |----------|-------------------------|
133
+ | Linux | GCC 11+ / Clang 14+ |
134
+ | macOS | Apple Clang 15+ / GCC 13+ (via Homebrew) |
135
+ | Windows | MSVC 2022 (19.30+) |
136
+
137
+ Pre-built wheels on [PyPI](https://pypi.org/project/docstring_generator_ext/) are compiled with C++20 enabled and require no special toolchain on the user's side.
138
+
139
+
92
140
  ## Authors
93
141
 
94
142
  - **FelixTheC**
@@ -97,3 +145,4 @@ The extension provides an enum `DocstringFormatStyle` to choose the desired outp
97
145
 
98
146
  This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.
99
147
 
148
+
@@ -0,0 +1,25 @@
1
+ MANIFEST.in
2
+ README.md
3
+ pyproject.toml
4
+ setup.py
5
+ docstring_generator_ext.egg-info/PKG-INFO
6
+ docstring_generator_ext.egg-info/SOURCES.txt
7
+ docstring_generator_ext.egg-info/dependency_links.txt
8
+ docstring_generator_ext.egg-info/requires.txt
9
+ docstring_generator_ext.egg-info/top_level.txt
10
+ src/FunctionFormat.cpp
11
+ src/FunctionFormat.hpp
12
+ src/GoogleDocstring.cpp
13
+ src/GoogleDocstring.hpp
14
+ src/IDocstringFormat.cpp
15
+ src/IDocstringFormat.hpp
16
+ src/NumpyDocstring.cpp
17
+ src/NumpyDocstring.hpp
18
+ src/ReStructuredDocstring.cpp
19
+ src/ReStructuredDocstring.hpp
20
+ src/docComparator.cpp
21
+ src/docComparator.hpp
22
+ src/docstringFormat.cpp
23
+ src/docstringFormat.hpp
24
+ src/parser.cpp
25
+ src/parser.hpp
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "docstring_generator_ext"
3
- version = "1.0.3a5"
3
+ version = "2.0.1"
4
4
  description = "Generate Docstrings with type-hint information."
5
5
  authors = [
6
6
  { name = "FelixTheC", email = "fberndt87@gmail.com" },
@@ -0,0 +1,59 @@
1
+ # Available at setup time due to pyproject.toml
2
+ import os
3
+ import platform
4
+ import shutil
5
+ from setuptools import setup
6
+ try:
7
+ from pybind11.setup_helpers import Pybind11Extension, build_ext
8
+ except ImportError:
9
+ from setuptools import Extension as Pybind11Extension
10
+ build_ext = None
11
+
12
+ # Ensure a modern system compiler is used instead of any toolchain compiler
13
+ # (e.g. GNAT's old g++) that may appear earlier on PATH.
14
+ def _find_compiler(names: list[str]) -> str | None:
15
+ for name in names:
16
+ path = shutil.which(name)
17
+ if path and "/GNAT" not in path and "/gnat" not in path:
18
+ return path
19
+ return None
20
+
21
+ # On macOS, cibuildwheel uses Apple Clang and controls -arch flags for
22
+ # cross-compilation (x86_64 / arm64). Overriding CC/CXX with a
23
+ # Homebrew GCC here would break that and produce a single-arch binary
24
+ # that delocate-wheel rejects. Only apply the GNAT-avoidance logic on
25
+ # Linux (and Windows, where shutil.which won't find g++ anyway).
26
+ if platform.system() != "Darwin":
27
+ if not os.environ.get("CC"):
28
+ cc = _find_compiler(["gcc-13", "gcc-14", "gcc-15", "gcc"])
29
+ if cc:
30
+ os.environ["CC"] = cc
31
+
32
+ if not os.environ.get("CXX"):
33
+ cxx = _find_compiler(["g++-13", "g++-14", "g++-15", "g++"])
34
+ if cxx:
35
+ os.environ["CXX"] = cxx
36
+
37
+
38
+ ext_modules = [
39
+ Pybind11Extension(
40
+ "docstring_generator_ext",
41
+ [
42
+ "src/docstringFormat.cpp",
43
+ "src/parser.cpp",
44
+ "src/FunctionFormat.cpp",
45
+ "src/IDocstringFormat.cpp",
46
+ "src/GoogleDocstring.cpp",
47
+ "src/NumpyDocstring.cpp",
48
+ "src/ReStructuredDocstring.cpp",
49
+ "src/docComparator.cpp",
50
+ ],
51
+ include_dirs=["src"],
52
+ cxx_std=20,
53
+ ),
54
+ ]
55
+
56
+ setup(
57
+ ext_modules=ext_modules,
58
+ cmdclass={"build_ext": build_ext} if build_ext else {},
59
+ )
@@ -0,0 +1,177 @@
1
+ #include "FunctionFormat.hpp"
2
+
3
+ #include <map>
4
+ #include "parser.hpp"
5
+
6
+ const std::map<std::string, ParameterKind> ParameterKinds = {
7
+ {"argument", ParameterKind::ARG},
8
+ {"positional only argument", ParameterKind::POS_ONLY},
9
+ {"keyword only argument", ParameterKind::KW_ONLY},
10
+ {"variadic argument", ParameterKind::VARIADIC_ARG},
11
+ {"keyword arguments", ParameterKind::KEYWORD_ARG},
12
+ };
13
+
14
+
15
+ ParameterKind from_str(const std::string &kind) {
16
+ const auto kind_lower = to_lower(kind);
17
+ if (const auto it = ParameterKinds.find(kind_lower); it != ParameterKinds.end()) {
18
+ return it->second;
19
+ }
20
+ return ParameterKind::ARG;
21
+ }
22
+
23
+ std::ostream &operator<<(std::ostream &out, ParameterKind const &obj) noexcept {
24
+ switch (obj) {
25
+ case ParameterKind::ARG:
26
+ return out << "Argument";
27
+ case ParameterKind::POS_ONLY:
28
+ return out << "Positional only argument";
29
+ case ParameterKind::KW_ONLY:
30
+ return out << "Keyword only argument";
31
+ case ParameterKind::VARIADIC_ARG:
32
+ return out << "Variadic arguments";
33
+ case ParameterKind::KEYWORD_ARG:
34
+ return out << "Keyword arguments";
35
+ }
36
+
37
+ return out;
38
+ }
39
+
40
+ void FunctionParameter::update_description(const std::string &descr, const DocstringFormatStyle &formatStyle) noexcept {
41
+ switch (formatStyle) {
42
+ case DocstringFormatStyle::reST:
43
+ update_rest_description(descr);
44
+ break;
45
+ case DocstringFormatStyle::GOOGLE:
46
+ case DocstringFormatStyle::NUMPY:
47
+ update_description(descr);
48
+ break;
49
+ }
50
+ }
51
+
52
+ void FunctionParameter::update_description(const std::string &descr) noexcept {
53
+ if (descr.empty()) {
54
+ return;
55
+ }
56
+
57
+ std::stringstream sstream;
58
+ sstream << kind;
59
+
60
+ const auto kind_name = sstream.str();
61
+ auto start_pos = descr.find(kind_name);
62
+
63
+ if (start_pos == std::string::npos)
64
+ start_pos = 0;
65
+ else {
66
+ start_pos += kind_name.size() + 2;
67
+ }
68
+
69
+ auto end_pos = descr.size();
70
+
71
+ if (!default_value.empty()) {
72
+ if (const auto default_pos = descr.find("default"); default_pos != std::string::npos)
73
+ end_pos = default_pos - 2;
74
+ }
75
+
76
+ if (end_pos != std::string::npos) {
77
+ const auto new_description = descr.substr(start_pos, end_pos - start_pos);
78
+ description = remove_whitespace(remove_trailing_whitespace(new_description));
79
+ }
80
+ }
81
+
82
+ void FunctionParameter::update_rest_description(const std::string &descr) noexcept {
83
+ auto param_name = ":param " + name + ":";
84
+ auto type_param = ":type " + name + ":";
85
+ auto kind_param = ":kind " + name + ":";
86
+ auto start_pos = descr.find(param_name);
87
+ if (start_pos == std::string::npos) {
88
+ return;
89
+ }
90
+
91
+ start_pos += param_name.size();
92
+ size_t end_pos = std::string::npos;
93
+
94
+ if (!default_value.empty()) {
95
+ end_pos = descr.find("(default is");
96
+ } else if (!type.empty()) {
97
+ end_pos = descr.find(type_param);
98
+ } else {
99
+ end_pos = descr.find(kind_param);
100
+ }
101
+
102
+ auto new_description = descr.substr(start_pos);
103
+
104
+ if (end_pos != std::string::npos) {
105
+ new_description = descr.substr(start_pos, end_pos - start_pos);
106
+ }
107
+
108
+ description = remove_whitespace(remove_trailing_whitespace(new_description));
109
+ }
110
+
111
+ [[nodiscard]] int FunctionInfo::get_file_write_position() const noexcept {
112
+ if (!docstring.docstring.empty()) {
113
+ return docstring.start_line;
114
+ }
115
+
116
+ if (returns.line_no > 0) {
117
+ return static_cast<int>(returns.line_no + 1);
118
+ }
119
+ if (!args.empty()) {
120
+ return static_cast<int>(args[args.size() - 1].line_no + 1);
121
+ }
122
+
123
+ return 0;
124
+ }
125
+
126
+ void FunctionInfo::update_descriptions(const DocstringFormatStyle &formatStyle) noexcept {
127
+ for (size_t idx = 0; idx < args.size(); ++idx) {
128
+ size_t start_pos;
129
+
130
+ if (formatStyle == DocstringFormatStyle::reST) {
131
+ start_pos = docstring.docstring.find(":param " + args[idx].name + ":");
132
+ } else {
133
+ start_pos = docstring.docstring.find(args[idx].name);
134
+ }
135
+
136
+ if (start_pos < std::string::npos) {
137
+ size_t end_pos = docstring.docstring.size() - 1;
138
+
139
+ if (idx < args.size() - 1) {
140
+ end_pos = docstring.docstring.find(args[idx + 1].name);
141
+ } else if (idx == args.size() - 1 && docstring.docstring.find("Returns") < std::string::npos) {
142
+ if (const auto return_pos = docstring.docstring.find("Returns"); return_pos != std::string::npos) {
143
+ end_pos = return_pos - 1;
144
+ }
145
+ }
146
+
147
+ if (end_pos != std::string::npos) {
148
+ std::string part_of_interest = docstring.docstring.substr(start_pos, end_pos - start_pos);
149
+ args[idx].update_description(part_of_interest, formatStyle);
150
+ }
151
+ }
152
+ }
153
+ }
154
+
155
+ FunctionDocstring get_docstring(const py::object &obj, const py::module &ast_module) noexcept {
156
+ FunctionDocstring functionDocstring{};
157
+
158
+ py::list body_list = py::getattr(obj, "body");
159
+ py::object body = body_list[0];
160
+
161
+ if (py::hasattr(body, "value")) {
162
+ py::object body_val = py::getattr(body, "value");
163
+
164
+ if (py::isinstance(body_val, ast_module.attr("Constant"))) {
165
+ try {
166
+ functionDocstring.docstring = py::cast<std::string>(py::getattr(body_val, "value"));
167
+ } catch (std::exception &) {
168
+ return functionDocstring;
169
+ }
170
+
171
+ functionDocstring.start_line = py::cast<uint32_t>(py::getattr(body_val, "lineno"));
172
+ functionDocstring.end_line = py::cast<uint32_t>(py::getattr(body_val, "end_lineno"));
173
+ }
174
+ }
175
+
176
+ return functionDocstring;
177
+ }
@@ -0,0 +1,72 @@
1
+ #ifndef DOCSTRING_GENERATOR_EXT_FUNCTIONFORMAT_HPP
2
+ #define DOCSTRING_GENERATOR_EXT_FUNCTIONFORMAT_HPP
3
+ #include <set>
4
+ #include <string>
5
+ #include <vector>
6
+
7
+ #include <pybind11/pybind11.h>
8
+ namespace py = pybind11;
9
+
10
+ enum class ParameterKind {
11
+ ARG,
12
+ POS_ONLY,
13
+ KW_ONLY,
14
+ VARIADIC_ARG,
15
+ KEYWORD_ARG,
16
+ };
17
+
18
+ enum class DocstringFormatStyle {
19
+ reST,
20
+ GOOGLE,
21
+ NUMPY
22
+ };
23
+
24
+ ParameterKind from_str(const std::string &kind);
25
+ std::ostream &operator<<(std::ostream &out, ParameterKind const &obj) noexcept;
26
+
27
+ struct FunctionParameter {
28
+ std::string name;
29
+ std::string default_value;
30
+ std::string type;
31
+ ParameterKind kind;
32
+ uint32_t line_no;
33
+ std::string description{};
34
+
35
+ void update_description(const std::string &descr, const DocstringFormatStyle &formatStyle) noexcept;
36
+ void update_description(const std::string &descr) noexcept;
37
+ void update_rest_description(const std::string &descr) noexcept;
38
+ };
39
+
40
+ struct FunctionReturn {
41
+ uint32_t line_no{};
42
+ std::string type;
43
+ std::string description;
44
+ };
45
+
46
+ struct FunctionDocstring {
47
+ uint32_t start_line{};
48
+ size_t end_line{};
49
+ std::string docstring;
50
+ };
51
+
52
+ FunctionDocstring get_docstring(const py::object &obj, const py::module &ast_module) noexcept;
53
+
54
+ struct FunctionException {
55
+ std::string name;
56
+ std::string description;
57
+
58
+ auto operator<=>(const FunctionException&) const = default;
59
+ };
60
+
61
+ struct FunctionInfo {
62
+ std::vector<FunctionParameter> args{};
63
+ uint32_t offset{};
64
+ FunctionDocstring docstring;
65
+ FunctionReturn returns;
66
+ std::set<FunctionException> exceptions {};
67
+
68
+ [[nodiscard]] int get_file_write_position() const noexcept;
69
+ void update_descriptions(const DocstringFormatStyle &formatStyle) noexcept;
70
+ };
71
+
72
+ #endif //DOCSTRING_GENERATOR_EXT_FUNCTIONFORMAT_HPP
@@ -0,0 +1,121 @@
1
+ #include "GoogleDocstring.hpp"
2
+
3
+ #include "parser.hpp"
4
+
5
+ void GoogleDocstring::check_current_docstring() noexcept {
6
+ auto current_py_tab = get_tabs();
7
+ auto google_args_begin = functionInfo.docstring.docstring.find("Args:");
8
+
9
+ if (google_args_begin < std::string::npos) {
10
+ functionInfo.docstring.docstring = functionInfo.docstring.docstring.substr(
11
+ 0,
12
+ google_args_begin - (current_py_tab.size() + 1)
13
+ );
14
+ functionInfo.docstring.end_line = functionInfo.docstring.start_line + google_args_begin;
15
+ }
16
+ }
17
+
18
+ std::string GoogleDocstring::docstringArgs() noexcept {
19
+ std::stringstream sstream;
20
+ auto current_py_tab = get_tabs();
21
+
22
+ if (!functionInfo.docstring.docstring.empty()) {
23
+ sstream << functionInfo.docstring.docstring;
24
+ sstream << "\n";
25
+ }
26
+
27
+ if (PY_TAB != current_py_tab) {
28
+ sstream << current_py_tab;
29
+ current_py_tab += PY_TAB;
30
+ } else {
31
+ sstream << PY_TAB;
32
+ current_py_tab = PY_TAB + PY_TAB;
33
+ }
34
+
35
+ sstream << "Args:\n";
36
+ std::ranges::for_each(functionInfo.args,
37
+ [&sstream, &current_py_tab](const FunctionParameter &val) {
38
+ sstream << current_py_tab << val.name;
39
+ if (!val.type.empty()) {
40
+ sstream << " (" << val.type;
41
+ if (!val.default_value.empty()) {
42
+ sstream << ", optional";
43
+ }
44
+ sstream << ")";
45
+ }
46
+
47
+ if (!val.description.empty()) {
48
+ sstream << ": " << val.description;
49
+ }
50
+
51
+ if (!val.default_value.empty()) {
52
+ sstream << " (default is " << val.default_value << ")\n";
53
+ }
54
+ }
55
+ );
56
+
57
+ return sstream.str();
58
+ }
59
+
60
+ std::string GoogleDocstring::docstringReturn() noexcept {
61
+ std::stringstream sstream;
62
+ auto current_py_tab = get_tabs();
63
+
64
+ if (!functionInfo.returns.description.empty() || !functionInfo.returns.type.empty()) {
65
+ sstream << "\n";
66
+
67
+ if (PY_TAB != current_py_tab) {
68
+ sstream << PY_TAB;
69
+ } else {
70
+ sstream << PY_TAB;
71
+ current_py_tab = PY_TAB + PY_TAB;
72
+ }
73
+
74
+ sstream << "Returns:\n";
75
+ sstream << current_py_tab;
76
+
77
+ if (!functionInfo.returns.type.empty()) {
78
+ sstream << functionInfo.returns.type << ": ";
79
+ }
80
+ if (!functionInfo.returns.description.empty()) {
81
+ sstream << functionInfo.returns.description;
82
+ }
83
+ } else {
84
+ sstream << "";
85
+ }
86
+
87
+ return sstream.str();
88
+ }
89
+
90
+ std::string GoogleDocstring::docstringExceptions() noexcept {
91
+ if (functionInfo.exceptions.empty())
92
+ return "\n";
93
+
94
+ std::stringstream sstream;
95
+ auto current_py_tab = get_tabs();
96
+
97
+ sstream << "\n";
98
+
99
+ if (PY_TAB != current_py_tab) {
100
+ sstream << PY_TAB;
101
+ } else {
102
+ sstream << PY_TAB;
103
+ current_py_tab = PY_TAB + PY_TAB;
104
+ }
105
+
106
+ sstream << "Raises:\n";
107
+ sstream << current_py_tab;
108
+
109
+ for (const auto &[name, description] : functionInfo.exceptions) {
110
+ if (!name.empty()) {
111
+ sstream << name << ": ";
112
+ }
113
+ if (!description.empty()) {
114
+ sstream << description;
115
+ }
116
+
117
+ sstream << "\n";
118
+ }
119
+
120
+ return sstream.str();
121
+ }