autodocgenerator 0.9.0.3__py3-none-any.whl → 0.9.2.5__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.
- autodocgenerator/__init__.py +21 -1
- autodocgenerator/auto_runner/run_file.py +4 -1
- autodocgenerator/config/config.py +2 -1
- autodocgenerator/engine/config/config.py +31 -18
- autodocgenerator/manage.py +16 -3
- autodocgenerator/preprocessor/compressor.py +6 -79
- autodocgenerator/preprocessor/spliter.py +9 -71
- autodocgenerator-0.9.2.5.dist-info/METADATA +786 -0
- {autodocgenerator-0.9.0.3.dist-info → autodocgenerator-0.9.2.5.dist-info}/RECORD +10 -10
- {autodocgenerator-0.9.0.3.dist-info → autodocgenerator-0.9.2.5.dist-info}/WHEEL +1 -1
- autodocgenerator-0.9.0.3.dist-info/METADATA +0 -983
autodocgenerator/__init__.py
CHANGED
|
@@ -1,4 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
def _print_welcome():
|
|
2
|
+
BLUE = "\033[94m"
|
|
3
|
+
BOLD = "\033[1m"
|
|
4
|
+
CYAN = "\033[96m"
|
|
5
|
+
RESET = "\033[0m"
|
|
6
|
+
|
|
7
|
+
ascii_logo = f"""
|
|
8
|
+
{BLUE}{BOLD} ___ ____ ______
|
|
9
|
+
/ | / __ \ / ____/
|
|
10
|
+
/ /| | / / / / / / __
|
|
11
|
+
/ ___ | / /_/ / / /_/ /
|
|
12
|
+
/_/ |_|/_____/ \____/
|
|
13
|
+
{RESET}"""
|
|
14
|
+
|
|
15
|
+
print(ascii_logo)
|
|
16
|
+
print(f"{CYAN}ADG Library{RESET} | {BOLD}Status:{RESET} Ready to work")
|
|
17
|
+
print(f"{'—' * 35}\n")
|
|
18
|
+
|
|
19
|
+
_print_welcome()
|
|
20
|
+
|
|
21
|
+
|
|
2
22
|
from .ui.logging import BaseLogger, BaseLoggerTemplate, InfoLog, ErrorLog, WarningLog
|
|
3
23
|
|
|
4
24
|
logger = BaseLogger()
|
|
@@ -26,7 +26,10 @@ def gen_doc(project_path: str,
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
manager.generate_code_file()
|
|
29
|
-
|
|
29
|
+
if config.pbc.use_global_file:
|
|
30
|
+
manager.generate_global_info(compress_power=4)
|
|
31
|
+
|
|
32
|
+
manager.generete_doc_parts(max_symbols=structure_settings.max_doc_part_size, with_global_file=config.pbc.use_global_file)
|
|
30
33
|
manager.factory_generate_doc(DocFactory(*custom_modules))
|
|
31
34
|
if structure_settings.include_order:
|
|
32
35
|
manager.order_doc()
|
|
@@ -7,6 +7,7 @@ from ..factory.modules.intro import IntroLinks
|
|
|
7
7
|
class ProjectBuildConfig:
|
|
8
8
|
save_logs = False
|
|
9
9
|
log_level = -1
|
|
10
|
+
use_global_file = True
|
|
10
11
|
def load_settings(self, data: dict[str, any]):
|
|
11
12
|
for key, el in data.items():
|
|
12
13
|
setattr(self, key, el)
|
|
@@ -15,7 +16,7 @@ class ProjectBuildConfig:
|
|
|
15
16
|
|
|
16
17
|
class Config:
|
|
17
18
|
def __init__(self):
|
|
18
|
-
self.ignore_files: list[str] = [
|
|
19
|
+
self.ignore_files: list[str] = ["*.pyo", "*.pyd", "*.pdb", "*.pkl", "*.log", "*.sqlite3", "*.db", "data",
|
|
19
20
|
"venv", "env", ".venv", ".env", ".vscode", ".idea", "*.iml", ".gitignore", ".ruff_cache", ".auto_doc_cache",
|
|
20
21
|
"*.pyc", "__pycache__", ".git", ".coverage", "htmlcov", "migrations", "*.md", "static", "staticfiles", ".mypy_cache"
|
|
21
22
|
]
|
|
@@ -124,24 +124,37 @@ This tag must appear ONLY ONCE at the very beginning. Never repeat it or use oth
|
|
|
124
124
|
|
|
125
125
|
def get_BASE_COMPRESS_TEXT(start, power):
|
|
126
126
|
return f"""
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
127
|
+
Task: Analyze the provided code snippet (~{start} chars) and generate a hyper-compressed Markdown architectural map.
|
|
128
|
+
Goal: Create a context baseline for other AI models so they understand the "big picture" and functional dependencies when looking at isolated parts of this code.
|
|
129
|
+
|
|
130
|
+
Constraints:
|
|
131
|
+
Strict Length: Maximum {int(start / power)} characters.
|
|
132
|
+
Format: Pure Markdown. Use visual markers (arrows, lists) for flow.
|
|
133
|
+
Tone: Technical, dense, no conversational filler.
|
|
134
|
+
|
|
135
|
+
Required Content:
|
|
136
|
+
Project Core: 1-sentence definition of the project's purpose and its architectural pattern (e.g., MVC, Layered, Event-driven).
|
|
137
|
+
Component Map: List main classes/modules and their primary responsibility.
|
|
138
|
+
Interaction Graph (Functional Context): Map how functions/methods interact.
|
|
139
|
+
|
|
140
|
+
Format: FunctionA -> FunctionB [data passed].
|
|
141
|
+
Highlight "Entry Points" (where logic starts) and "Terminal Points" (where data is saved/returned).
|
|
142
|
+
State & Context: Mention key shared objects or state variables that influence multiple functions.
|
|
143
|
+
|
|
144
|
+
Output Structure:
|
|
145
|
+
Markdown
|
|
146
|
+
## Architecture: [Name/Pattern]
|
|
147
|
+
**Goal:** [Brief description]
|
|
148
|
+
|
|
149
|
+
### Component Logic
|
|
150
|
+
* **[Class/Module]:** [Responsibility]
|
|
151
|
+
|
|
152
|
+
### Functional Flow (Dependencies)
|
|
153
|
+
* `Method_1` -> calls `Method_2` to [reason]
|
|
154
|
+
* `Method_2` -> updates `SharedState` -> triggers `Method_3`
|
|
155
|
+
|
|
156
|
+
### Key Context for Snippets
|
|
157
|
+
[List critical dependencies or global variables a developer must know to edit any single function here]
|
|
145
158
|
"""
|
|
146
159
|
|
|
147
160
|
import os
|
autodocgenerator/manage.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from .preprocessor.spliter import split_data, gen_doc_parts
|
|
2
|
-
from .preprocessor.compressor import compress_to_one
|
|
1
|
+
from .preprocessor.spliter import split_data, gen_doc_parts
|
|
2
|
+
from .preprocessor.compressor import compress_to_one
|
|
3
3
|
from .postprocessor.custom_intro import get_introdaction, get_all_html_links, get_links_intro
|
|
4
4
|
from .engine.models.gpt_model import AsyncGPTModel, GPTModel
|
|
5
5
|
from .engine.models.model import Model, AsyncModel
|
|
@@ -67,8 +67,21 @@ class Manager:
|
|
|
67
67
|
self.logger.log(InfoLog("Code mix generation completed."))
|
|
68
68
|
self.progress_bar.update_task()
|
|
69
69
|
|
|
70
|
-
def
|
|
70
|
+
def generate_global_info(self, compress_power: int = 4, max_symbols: int = 10000):
|
|
71
71
|
full_code_mix = self.read_file_by_file_key("code_mix")
|
|
72
|
+
data = split_data(full_code_mix, max_symbols)
|
|
73
|
+
|
|
74
|
+
global_result = compress_to_one(data, self.sync_model, self.config.get_project_settings(), compress_power=compress_power, progress_bar=self.progress_bar)
|
|
75
|
+
with open(self.get_file_path("global_info"), "w", encoding="utf-8") as file:
|
|
76
|
+
file.write(global_result)
|
|
77
|
+
|
|
78
|
+
self.progress_bar.update_task()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def generete_doc_parts(self, max_symbols=5_000, with_global_file: bool = False):
|
|
82
|
+
full_code_mix = self.read_file_by_file_key("code_mix")
|
|
83
|
+
|
|
84
|
+
global_file = self.read_file_by_file_key("global_info") if with_global_file else None
|
|
72
85
|
|
|
73
86
|
self.logger.log(InfoLog("Starting synchronous documentation generation by parts..."))
|
|
74
87
|
result = gen_doc_parts(full_code_mix,
|
|
@@ -16,7 +16,7 @@ def compress(data: str, project_settings: ProjectSettings, model: Model, compres
|
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
"role": "system",
|
|
19
|
-
"content": get_BASE_COMPRESS_TEXT(
|
|
19
|
+
"content": get_BASE_COMPRESS_TEXT(len(data), compress_power)
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
"role": "user",
|
|
@@ -40,58 +40,18 @@ def compress_and_compare(data: list, model: Model, project_settings: ProjectSett
|
|
|
40
40
|
|
|
41
41
|
return compress_and_compare_data
|
|
42
42
|
|
|
43
|
-
async def async_compress(data: str, project_settings: ProjectSettings, model: AsyncModel, compress_power, semaphore, progress_bar: BaseProgress) -> str:
|
|
44
|
-
|
|
45
|
-
async with semaphore:
|
|
46
|
-
prompt = [
|
|
47
|
-
{
|
|
48
|
-
"role": "system",
|
|
49
|
-
"content": project_settings.prompt
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
"role": "system",
|
|
53
|
-
"content": get_BASE_COMPRESS_TEXT(10000, compress_power)
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
"role": "user",
|
|
57
|
-
"content": data
|
|
58
|
-
}
|
|
59
|
-
]
|
|
60
|
-
answer = await model.get_answer_without_history(prompt=prompt)
|
|
61
|
-
progress_bar.update_task()
|
|
62
|
-
return answer
|
|
63
|
-
|
|
64
|
-
async def async_compress_and_compare(data: list, model: AsyncModel, project_settings: ProjectSettings, compress_power: int = 4, progress_bar: BaseProgress = BaseProgress()) -> list:
|
|
65
|
-
semaphore = asyncio.Semaphore(4)
|
|
66
|
-
tasks = []
|
|
67
|
-
progress_bar.create_new_subtask(f"Compare all files (async)", len(data))
|
|
68
|
-
|
|
69
|
-
for el in data:
|
|
70
|
-
tasks.append(async_compress(el, project_settings, model, compress_power, semaphore, progress_bar))
|
|
71
|
-
|
|
72
|
-
compressed_elements = await asyncio.gather(*tasks)
|
|
73
|
-
|
|
74
|
-
final_data = []
|
|
75
|
-
chunk_size = compress_power
|
|
76
|
-
for i in range(0, len(compressed_elements), chunk_size):
|
|
77
|
-
chunk = compressed_elements[i : i + chunk_size]
|
|
78
|
-
final_data.append("\n".join(chunk) + "\n")
|
|
79
|
-
|
|
80
|
-
progress_bar.remove_subtask()
|
|
81
|
-
|
|
82
|
-
return final_data
|
|
83
43
|
|
|
84
|
-
|
|
44
|
+
|
|
45
|
+
def compress_to_one(data: list, model: Model, project_settings: ProjectSettings, compress_power: int = 4, progress_bar: BaseProgress = BaseProgress()):
|
|
85
46
|
count_of_iter = 0
|
|
47
|
+
|
|
86
48
|
while len(data) > 1:
|
|
87
49
|
new_compress_power = compress_power
|
|
88
50
|
if (len(data) < compress_power + 1):
|
|
89
51
|
new_compress_power = 2
|
|
90
52
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
else:
|
|
94
|
-
data = compress_and_compare(data, model, project_settings, new_compress_power, progress_bar=progress_bar)
|
|
53
|
+
data = compress_and_compare(data, model, project_settings, new_compress_power, progress_bar=progress_bar)
|
|
54
|
+
|
|
95
55
|
count_of_iter += 1
|
|
96
56
|
|
|
97
57
|
|
|
@@ -99,39 +59,6 @@ def compress_to_one(data: list, model: Model, project_settings: ProjectSettings,
|
|
|
99
59
|
|
|
100
60
|
|
|
101
61
|
|
|
102
|
-
def generate_discribtions_for_code(data: list, model: Model, project_settings: ProjectSettings, progress_bar: BaseProgress = BaseProgress()) -> list:
|
|
103
|
-
describtions = []
|
|
104
|
-
progress_bar.create_new_subtask("Generate describtions for code files", len(data))
|
|
105
|
-
for code in data:
|
|
106
|
-
prompt = [
|
|
107
|
-
{
|
|
108
|
-
"role": "system",
|
|
109
|
-
"content": """### Instructions:
|
|
110
|
-
1. Identify Main Components: Determine what classes, functions, or modules are meant to be used by an external developer.
|
|
111
|
-
2. Description: Explain the purpose of each main component (e.g., "What is the Manager class for?").
|
|
112
|
-
3. Parameters & Types: Detail every parameter required for initialization and method calls, including their expected data types and default values.
|
|
113
|
-
4. Usage Example: Provide a COMPLETE, "copy-pasteable" code example showing:
|
|
114
|
-
- Proper initialization.
|
|
115
|
-
- Calling key methods.
|
|
116
|
-
- Handling expected outputs or errors.
|
|
117
|
-
|
|
118
|
-
### Strict Rules:
|
|
119
|
-
- Base your guide ONLY on the provided code.
|
|
120
|
-
- If the code is incomplete or a certain class/method is missing, do not hallucinate its logic—simply state that information is unavailable.
|
|
121
|
-
- Use Markdown for code blocks and bold text for parameter names.
|
|
122
|
-
- If no usable logic is found in the code, respond with an empty string ("")."""
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
"role": "user",
|
|
126
|
-
"content": f"CONTEXT: {code}"
|
|
127
|
-
}
|
|
128
|
-
]
|
|
129
|
-
answer = model.get_answer_without_history(prompt=prompt)
|
|
130
|
-
describtions.append(answer)
|
|
131
|
-
progress_bar.update_task()
|
|
132
|
-
|
|
133
|
-
progress_bar.remove_subtask()
|
|
134
|
-
return describtions
|
|
135
62
|
|
|
136
63
|
|
|
137
64
|
|
|
@@ -41,7 +41,7 @@ def split_data(data: str, max_symbols: int) -> list[str]:
|
|
|
41
41
|
|
|
42
42
|
return split_objects
|
|
43
43
|
|
|
44
|
-
def write_docs_by_parts(part: str, model: Model, project_settings: ProjectSettings, prev_info: str = None, language: str = "en"):
|
|
44
|
+
def write_docs_by_parts(part: str, model: Model, project_settings: ProjectSettings, prev_info: str = None, language: str = "en", global_info: str = None):
|
|
45
45
|
logger = BaseLogger()
|
|
46
46
|
logger.log(InfoLog("Generating documentation for a part..."))
|
|
47
47
|
prompt = [
|
|
@@ -59,6 +59,12 @@ def write_docs_by_parts(part: str, model: Model, project_settings: ProjectSettin
|
|
|
59
59
|
}
|
|
60
60
|
]
|
|
61
61
|
|
|
62
|
+
if global_info is not None:
|
|
63
|
+
prompt.append({
|
|
64
|
+
"role": "system",
|
|
65
|
+
"content": f"global relations in project: {global_info}"
|
|
66
|
+
})
|
|
67
|
+
|
|
62
68
|
if prev_info is not None:
|
|
63
69
|
prompt.append({
|
|
64
70
|
"role": "system",
|
|
@@ -80,53 +86,10 @@ def write_docs_by_parts(part: str, model: Model, project_settings: ProjectSettin
|
|
|
80
86
|
answer = temp_answer.removesuffix("```")
|
|
81
87
|
return answer
|
|
82
88
|
|
|
83
|
-
async def async_write_docs_by_parts(part: str, async_model: AsyncModel, global_info: str, semaphore, prev_info: str = None, language: str = "en", update_progress = None):
|
|
84
|
-
logger = BaseLogger()
|
|
85
|
-
logger.log(InfoLog("Generating documentation for a part (async)..."))
|
|
86
|
-
async with semaphore:
|
|
87
89
|
|
|
88
|
-
prompt = [
|
|
89
|
-
{
|
|
90
|
-
"role": "system",
|
|
91
|
-
"content": f"For the following task use language {language}"
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
"role": "system",
|
|
95
|
-
"content": BASE_PART_COMPLITE_TEXT
|
|
96
|
-
},
|
|
97
|
-
|
|
98
|
-
{
|
|
99
|
-
"role": "user",
|
|
100
|
-
"content": part
|
|
101
|
-
}
|
|
102
|
-
]
|
|
103
90
|
|
|
104
|
-
if prev_info is not None:
|
|
105
|
-
prompt.append({
|
|
106
|
-
"role": "system",
|
|
107
|
-
"content": f"it is last part of documentation that you have write before {prev_info}"
|
|
108
|
-
})
|
|
109
91
|
|
|
110
|
-
|
|
111
|
-
"role": "user",
|
|
112
|
-
"content": part
|
|
113
|
-
})
|
|
114
|
-
answer: str = await async_model.get_answer_without_history(prompt=prompt)
|
|
115
|
-
|
|
116
|
-
if update_progress is not None:
|
|
117
|
-
update_progress()
|
|
118
|
-
|
|
119
|
-
logger.log(InfoLog("Documentation for part generated. total length: " + str(len(answer))))
|
|
120
|
-
logger.log(InfoLog(f"Part Documentation: {answer}", level=2))
|
|
121
|
-
temp_answer = answer.removeprefix("```")
|
|
122
|
-
if answer == temp_answer:
|
|
123
|
-
return answer
|
|
124
|
-
|
|
125
|
-
answer = temp_answer.removesuffix("```")
|
|
126
|
-
return answer
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
def gen_doc_parts(full_code_mix, max_symbols, model: Model, project_settings: ProjectSettings, language, progress_bar: BaseProgress):
|
|
92
|
+
def gen_doc_parts(full_code_mix, max_symbols, model: Model, project_settings: ProjectSettings, language, progress_bar: BaseProgress, global_info = None):
|
|
130
93
|
splited_data = split_data(full_code_mix, max_symbols)
|
|
131
94
|
result = None
|
|
132
95
|
logger = BaseLogger()
|
|
@@ -136,7 +99,7 @@ def gen_doc_parts(full_code_mix, max_symbols, model: Model, project_settings: Pr
|
|
|
136
99
|
|
|
137
100
|
all_result = ""
|
|
138
101
|
for i, el in enumerate(splited_data):
|
|
139
|
-
result = write_docs_by_parts(el, model, project_settings, result, language)
|
|
102
|
+
result = write_docs_by_parts(el, model, project_settings, result, language, global_info=global_info)
|
|
140
103
|
all_result += result
|
|
141
104
|
all_result += "\n\n"
|
|
142
105
|
|
|
@@ -148,28 +111,3 @@ def gen_doc_parts(full_code_mix, max_symbols, model: Model, project_settings: Pr
|
|
|
148
111
|
Total documentation length: {len(all_result)}"""))
|
|
149
112
|
logger.log(InfoLog(f"Documentation: {all_result}", level=2))
|
|
150
113
|
return all_result
|
|
151
|
-
|
|
152
|
-
async def async_gen_doc_parts(full_code_mix, global_info, max_symbols, model: AsyncModel, language, progress_bar: BaseProgress):
|
|
153
|
-
splited_data = split_data(full_code_mix, max_symbols)
|
|
154
|
-
progress_bar.create_new_subtask(f"Generete doc parts (async)", len(splited_data))
|
|
155
|
-
|
|
156
|
-
semaphore = asyncio.Semaphore(4)
|
|
157
|
-
logger = BaseLogger()
|
|
158
|
-
logger.log(InfoLog("Starting asynchronous documentation generation by parts..."))
|
|
159
|
-
|
|
160
|
-
tasks = []
|
|
161
|
-
for el in splited_data:
|
|
162
|
-
tasks.append(async_write_docs_by_parts(part=el, async_model=model, global_info=global_info, semaphore=semaphore, language=language, update_progress=lambda: progress_bar.update_task()))
|
|
163
|
-
|
|
164
|
-
gen_parts = await asyncio.gather(*tasks)
|
|
165
|
-
result = ""
|
|
166
|
-
for el in gen_parts:
|
|
167
|
-
result += el
|
|
168
|
-
result += "\n\n"
|
|
169
|
-
|
|
170
|
-
progress_bar.remove_subtask()
|
|
171
|
-
logger.log(InfoLog(f"""Asynchronous documentation generation by parts completed.\n
|
|
172
|
-
Total documentation length: {len(result)}"""))
|
|
173
|
-
logger.log(InfoLog(f"Documentation: {result}", level=2))
|
|
174
|
-
|
|
175
|
-
return result
|