pdd-cli 0.0.38__py3-none-any.whl → 0.0.40__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.
Potentially problematic release.
This version of pdd-cli might be problematic. Click here for more details.
- pdd/__init__.py +5 -4
- pdd/auto_deps_main.py +14 -7
- pdd/auto_include.py +147 -98
- pdd/auto_update.py +24 -11
- pdd/bug_main.py +5 -2
- pdd/bug_to_unit_test.py +9 -2
- pdd/change.py +32 -22
- pdd/change_main.py +14 -10
- pdd/cli.py +11 -1
- pdd/cmd_test_main.py +7 -3
- pdd/code_generator.py +7 -1
- pdd/code_generator_main.py +9 -3
- pdd/conflicts_in_prompts.py +7 -2
- pdd/conflicts_main.py +6 -2
- pdd/context_generator.py +20 -3
- pdd/context_generator_main.py +2 -0
- pdd/continue_generation.py +8 -2
- pdd/crash_main.py +51 -31
- pdd/detect_change.py +8 -4
- pdd/detect_change_main.py +3 -0
- pdd/fix_code_loop.py +7 -2
- pdd/fix_code_module_errors.py +5 -2
- pdd/fix_error_loop.py +6 -2
- pdd/fix_errors_from_unit_tests.py +11 -6
- pdd/fix_main.py +4 -0
- pdd/fix_verification_errors.py +8 -3
- pdd/fix_verification_errors_loop.py +9 -3
- pdd/fix_verification_main.py +37 -31
- pdd/generate_test.py +10 -4
- pdd/get_extension.py +23 -9
- pdd/git_update.py +5 -3
- pdd/increase_tests.py +5 -2
- pdd/insert_includes.py +8 -2
- pdd/preprocess_main.py +10 -3
- pdd/process_csv_change.py +8 -2
- pdd/split.py +15 -7
- pdd/split_main.py +2 -0
- pdd/summarize_directory.py +4 -0
- pdd/trace.py +9 -5
- pdd/trace_main.py +5 -4
- pdd/unfinished_prompt.py +6 -1
- pdd/update_main.py +6 -3
- pdd/update_prompt.py +8 -4
- pdd/xml_tagger.py +10 -5
- {pdd_cli-0.0.38.dist-info → pdd_cli-0.0.40.dist-info}/METADATA +4 -4
- {pdd_cli-0.0.38.dist-info → pdd_cli-0.0.40.dist-info}/RECORD +50 -50
- {pdd_cli-0.0.38.dist-info → pdd_cli-0.0.40.dist-info}/WHEEL +0 -0
- {pdd_cli-0.0.38.dist-info → pdd_cli-0.0.40.dist-info}/entry_points.txt +0 -0
- {pdd_cli-0.0.38.dist-info → pdd_cli-0.0.40.dist-info}/licenses/LICENSE +0 -0
- {pdd_cli-0.0.38.dist-info → pdd_cli-0.0.40.dist-info}/top_level.txt +0 -0
pdd/__init__.py
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
"""PDD - Prompt Driven Development"""
|
|
2
|
+
|
|
3
|
+
__version__ = "0.0.40"
|
|
2
4
|
|
|
3
5
|
# Strength parameter used for LLM extraction across the codebase
|
|
4
|
-
# Used in postprocessing, XML tagging, code generation, and other extraction
|
|
6
|
+
# Used in postprocessing, XML tagging, code generation, and other extraction
|
|
7
|
+
# operations. The module should have a large context window and be affordable.
|
|
5
8
|
EXTRACTION_STRENGTH = 0.9
|
|
6
9
|
|
|
7
10
|
DEFAULT_STRENGTH = 0.9
|
|
@@ -10,8 +13,6 @@ DEFAULT_TEMPERATURE = 0.0
|
|
|
10
13
|
|
|
11
14
|
DEFAULT_TIME = 0.25
|
|
12
15
|
|
|
13
|
-
"""PDD - Prompt Driven Development"""
|
|
14
|
-
|
|
15
16
|
# Define constants used across the package
|
|
16
17
|
DEFAULT_LLM_MODEL = "gpt-4.1-nano"
|
|
17
18
|
# When going to production, set the following constants:
|
pdd/auto_deps_main.py
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
"""Main function for the auto-deps command."""
|
|
1
2
|
import sys
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
from typing import Tuple, Optional
|
|
4
5
|
import click
|
|
5
6
|
from rich import print as rprint
|
|
6
7
|
|
|
8
|
+
from . import DEFAULT_STRENGTH, DEFAULT_TIME
|
|
7
9
|
from .construct_paths import construct_paths
|
|
8
10
|
from .insert_includes import insert_includes
|
|
9
11
|
|
|
10
|
-
def auto_deps_main(
|
|
12
|
+
def auto_deps_main( # pylint: disable=too-many-arguments, too-many-locals
|
|
11
13
|
ctx: click.Context,
|
|
12
14
|
prompt_file: str,
|
|
13
15
|
directory_path: str,
|
|
@@ -56,12 +58,16 @@ def auto_deps_main(
|
|
|
56
58
|
# Handle force_scan option
|
|
57
59
|
if force_scan and Path(csv_path).exists():
|
|
58
60
|
if not ctx.obj.get('quiet', False):
|
|
59
|
-
rprint(
|
|
61
|
+
rprint(
|
|
62
|
+
"[yellow]Removing existing CSV file due to "
|
|
63
|
+
f"--force-scan option: {csv_path}[/yellow]"
|
|
64
|
+
)
|
|
60
65
|
Path(csv_path).unlink()
|
|
61
66
|
|
|
62
67
|
# Get strength and temperature from context
|
|
63
|
-
strength = ctx.obj.get('strength',
|
|
68
|
+
strength = ctx.obj.get('strength', DEFAULT_STRENGTH)
|
|
64
69
|
temperature = ctx.obj.get('temperature', 0)
|
|
70
|
+
time_budget = ctx.obj.get('time', DEFAULT_TIME)
|
|
65
71
|
|
|
66
72
|
# Call insert_includes with the prompt content and directory path
|
|
67
73
|
modified_prompt, csv_output, total_cost, model_name = insert_includes(
|
|
@@ -70,16 +76,17 @@ def auto_deps_main(
|
|
|
70
76
|
csv_filename=csv_path,
|
|
71
77
|
strength=strength,
|
|
72
78
|
temperature=temperature,
|
|
79
|
+
time=time_budget,
|
|
73
80
|
verbose=not ctx.obj.get('quiet', False)
|
|
74
81
|
)
|
|
75
82
|
|
|
76
83
|
# Save the modified prompt to the output file
|
|
77
84
|
output_path = output_file_paths["output"]
|
|
78
|
-
Path(output_path).write_text(modified_prompt)
|
|
85
|
+
Path(output_path).write_text(modified_prompt, encoding="utf-8")
|
|
79
86
|
|
|
80
87
|
# Save the CSV output if it was generated
|
|
81
88
|
if csv_output:
|
|
82
|
-
Path(csv_path).write_text(csv_output)
|
|
89
|
+
Path(csv_path).write_text(csv_output, encoding="utf-8")
|
|
83
90
|
|
|
84
91
|
# Provide user feedback
|
|
85
92
|
if not ctx.obj.get('quiet', False):
|
|
@@ -91,7 +98,7 @@ def auto_deps_main(
|
|
|
91
98
|
|
|
92
99
|
return modified_prompt, total_cost, model_name
|
|
93
100
|
|
|
94
|
-
except Exception as
|
|
101
|
+
except Exception as exc:
|
|
95
102
|
if not ctx.obj.get('quiet', False):
|
|
96
|
-
rprint(f"[bold red]Error:[/bold red] {str(
|
|
103
|
+
rprint(f"[bold red]Error:[/bold red] {str(exc)}")
|
|
97
104
|
sys.exit(1)
|
pdd/auto_include.py
CHANGED
|
@@ -1,25 +1,120 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides the `auto_include` function to automatically find and
|
|
3
|
+
insert dependencies into a prompt.
|
|
4
|
+
"""
|
|
5
|
+
from io import StringIO
|
|
1
6
|
from typing import Tuple, Optional
|
|
7
|
+
|
|
8
|
+
import pandas as pd
|
|
2
9
|
from pydantic import BaseModel, Field
|
|
3
|
-
from rich import print
|
|
4
10
|
from rich.console import Console
|
|
5
11
|
from rich.panel import Panel
|
|
6
|
-
|
|
12
|
+
|
|
13
|
+
from . import DEFAULT_TIME, DEFAULT_STRENGTH
|
|
7
14
|
from .llm_invoke import llm_invoke
|
|
15
|
+
from .load_prompt_template import load_prompt_template
|
|
8
16
|
from .summarize_directory import summarize_directory
|
|
9
|
-
import pandas as pd
|
|
10
|
-
from io import StringIO
|
|
11
17
|
|
|
12
18
|
console = Console()
|
|
13
19
|
|
|
14
20
|
class AutoIncludeOutput(BaseModel):
|
|
21
|
+
"""
|
|
22
|
+
Pydantic model for the output of the auto_include extraction.
|
|
23
|
+
"""
|
|
15
24
|
string_of_includes: str = Field(description="The string of includes to be added to the prompt")
|
|
16
25
|
|
|
26
|
+
|
|
27
|
+
def _validate_input(input_prompt: str, directory_path: str, strength: float, temperature: float):
|
|
28
|
+
"""Validate the inputs for the auto_include function."""
|
|
29
|
+
if not input_prompt:
|
|
30
|
+
raise ValueError("Input prompt cannot be empty")
|
|
31
|
+
if not directory_path:
|
|
32
|
+
raise ValueError("Invalid 'directory_path'.")
|
|
33
|
+
if not 0 <= strength <= 1:
|
|
34
|
+
raise ValueError("Strength must be between 0 and 1")
|
|
35
|
+
if not 0 <= temperature <= 1:
|
|
36
|
+
raise ValueError("Temperature must be between 0 and 1")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _get_available_includes_from_csv(csv_output: str) -> list[str]:
|
|
40
|
+
"""Parse the CSV output and return a list of available includes."""
|
|
41
|
+
if not csv_output:
|
|
42
|
+
return []
|
|
43
|
+
try:
|
|
44
|
+
# pylint: disable=invalid-name
|
|
45
|
+
dataframe = pd.read_csv(StringIO(csv_output))
|
|
46
|
+
return dataframe.apply(
|
|
47
|
+
lambda row: f"File: {row['full_path']}\nSummary: {row['file_summary']}",
|
|
48
|
+
axis=1
|
|
49
|
+
).tolist()
|
|
50
|
+
except Exception as ex:
|
|
51
|
+
console.print(f"[red]Error parsing CSV: {str(ex)}[/red]")
|
|
52
|
+
return []
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _load_prompts() -> tuple[str, str]:
|
|
56
|
+
"""Load the prompt templates."""
|
|
57
|
+
auto_include_prompt = load_prompt_template("auto_include_LLM")
|
|
58
|
+
extract_prompt = load_prompt_template("extract_auto_include_LLM")
|
|
59
|
+
if not auto_include_prompt or not extract_prompt:
|
|
60
|
+
raise ValueError("Failed to load prompt templates")
|
|
61
|
+
return auto_include_prompt, extract_prompt
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _summarize(directory_path: str, csv_file: Optional[str], llm_kwargs: dict) -> tuple[str, float, str]:
|
|
65
|
+
"""Summarize the directory."""
|
|
66
|
+
return summarize_directory(
|
|
67
|
+
directory_path=directory_path,
|
|
68
|
+
csv_file=csv_file,
|
|
69
|
+
**llm_kwargs
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _run_llm_and_extract(
|
|
74
|
+
auto_include_prompt: str,
|
|
75
|
+
extract_prompt: str,
|
|
76
|
+
input_prompt: str,
|
|
77
|
+
available_includes: list[str],
|
|
78
|
+
llm_kwargs: dict,
|
|
79
|
+
) -> tuple[str, float, str]:
|
|
80
|
+
"""Run the LLM prompts and extract the dependencies."""
|
|
81
|
+
# pylint: disable=broad-except
|
|
82
|
+
# Run auto_include_LLM prompt
|
|
83
|
+
auto_include_response = llm_invoke(
|
|
84
|
+
prompt=auto_include_prompt,
|
|
85
|
+
input_json={
|
|
86
|
+
"input_prompt": input_prompt,
|
|
87
|
+
"available_includes": "\n".join(available_includes)
|
|
88
|
+
},
|
|
89
|
+
**llm_kwargs
|
|
90
|
+
)
|
|
91
|
+
total_cost = auto_include_response["cost"]
|
|
92
|
+
model_name = auto_include_response["model_name"]
|
|
93
|
+
|
|
94
|
+
# Run extract_auto_include_LLM prompt
|
|
95
|
+
try:
|
|
96
|
+
extract_response = llm_invoke(
|
|
97
|
+
prompt=extract_prompt,
|
|
98
|
+
input_json={"llm_output": auto_include_response["result"]},
|
|
99
|
+
output_pydantic=AutoIncludeOutput,
|
|
100
|
+
**llm_kwargs
|
|
101
|
+
)
|
|
102
|
+
total_cost += extract_response["cost"]
|
|
103
|
+
model_name = extract_response["model_name"]
|
|
104
|
+
dependencies = extract_response["result"].string_of_includes
|
|
105
|
+
except Exception as ex:
|
|
106
|
+
console.print(f"[red]Error extracting dependencies: {str(ex)}[/red]")
|
|
107
|
+
dependencies = ""
|
|
108
|
+
return dependencies, total_cost, model_name
|
|
109
|
+
|
|
110
|
+
|
|
17
111
|
def auto_include(
|
|
18
112
|
input_prompt: str,
|
|
19
113
|
directory_path: str,
|
|
20
114
|
csv_file: Optional[str] = None,
|
|
21
|
-
strength: float =
|
|
115
|
+
strength: float = DEFAULT_STRENGTH,
|
|
22
116
|
temperature: float = 0.0,
|
|
117
|
+
time: float = DEFAULT_TIME,
|
|
23
118
|
verbose: bool = False
|
|
24
119
|
) -> Tuple[str, str, float, str]:
|
|
25
120
|
"""
|
|
@@ -31,135 +126,89 @@ def auto_include(
|
|
|
31
126
|
csv_file (Optional[str]): Contents of existing CSV file
|
|
32
127
|
strength (float): Strength of LLM model (0-1)
|
|
33
128
|
temperature (float): Temperature of LLM model (0-1)
|
|
129
|
+
time (float): Time budget for LLM calls
|
|
34
130
|
verbose (bool): Whether to print detailed information
|
|
35
131
|
|
|
36
132
|
Returns:
|
|
37
133
|
Tuple[str, str, float, str]: (dependencies, csv_output, total_cost, model_name)
|
|
38
134
|
"""
|
|
135
|
+
# pylint: disable=broad-except
|
|
39
136
|
try:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
raise ValueError("Temperature must be between 0 and 1")
|
|
49
|
-
|
|
50
|
-
total_cost = 0.0
|
|
51
|
-
model_name = ""
|
|
137
|
+
_validate_input(input_prompt, directory_path, strength, temperature)
|
|
138
|
+
|
|
139
|
+
llm_kwargs = {
|
|
140
|
+
"strength": strength,
|
|
141
|
+
"temperature": temperature,
|
|
142
|
+
"time": time,
|
|
143
|
+
"verbose": verbose
|
|
144
|
+
}
|
|
52
145
|
|
|
53
146
|
if verbose:
|
|
54
147
|
console.print(Panel("Step 1: Loading prompt templates", style="blue"))
|
|
55
148
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
extract_prompt = load_prompt_template("extract_auto_include_LLM")
|
|
59
|
-
|
|
60
|
-
if not auto_include_prompt or not extract_prompt:
|
|
61
|
-
raise ValueError("Failed to load prompt templates")
|
|
62
|
-
|
|
149
|
+
auto_include_prompt, extract_prompt = _load_prompts()
|
|
150
|
+
|
|
63
151
|
if verbose:
|
|
64
152
|
console.print(Panel("Step 2: Running summarize_directory", style="blue"))
|
|
65
153
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
directory_path=directory_path,
|
|
69
|
-
strength=strength,
|
|
70
|
-
temperature=temperature,
|
|
71
|
-
verbose=verbose,
|
|
72
|
-
csv_file=csv_file
|
|
154
|
+
csv_output, summary_cost, summary_model = _summarize(
|
|
155
|
+
directory_path, csv_file, llm_kwargs
|
|
73
156
|
)
|
|
74
|
-
total_cost += summary_cost
|
|
75
|
-
model_name = summary_model
|
|
76
|
-
|
|
77
|
-
# Parse CSV to get available includes
|
|
78
|
-
if not csv_output:
|
|
79
|
-
available_includes = []
|
|
80
|
-
else:
|
|
81
|
-
try:
|
|
82
|
-
df = pd.read_csv(StringIO(csv_output))
|
|
83
|
-
available_includes = df.apply(
|
|
84
|
-
lambda row: f"File: {row['full_path']}\nSummary: {row['file_summary']}",
|
|
85
|
-
axis=1
|
|
86
|
-
).tolist()
|
|
87
|
-
except Exception as e:
|
|
88
|
-
console.print(f"[red]Error parsing CSV: {str(e)}[/red]")
|
|
89
|
-
available_includes = []
|
|
90
157
|
|
|
158
|
+
available_includes = _get_available_includes_from_csv(csv_output)
|
|
159
|
+
|
|
91
160
|
if verbose:
|
|
92
161
|
console.print(Panel("Step 3: Running auto_include_LLM prompt", style="blue"))
|
|
93
162
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
},
|
|
101
|
-
strength=strength,
|
|
102
|
-
temperature=temperature,
|
|
103
|
-
verbose=verbose
|
|
163
|
+
dependencies, llm_cost, llm_model_name = _run_llm_and_extract(
|
|
164
|
+
auto_include_prompt=auto_include_prompt,
|
|
165
|
+
extract_prompt=extract_prompt,
|
|
166
|
+
input_prompt=input_prompt,
|
|
167
|
+
available_includes=available_includes,
|
|
168
|
+
llm_kwargs=llm_kwargs,
|
|
104
169
|
)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if verbose:
|
|
109
|
-
console.print(Panel("Step 4: Running extract_auto_include_LLM prompt", style="blue"))
|
|
110
|
-
|
|
111
|
-
# Run extract_auto_include_LLM prompt
|
|
112
|
-
try:
|
|
113
|
-
extract_response = llm_invoke(
|
|
114
|
-
prompt=extract_prompt,
|
|
115
|
-
input_json={"llm_output": auto_include_response["result"]},
|
|
116
|
-
strength=strength,
|
|
117
|
-
temperature=temperature,
|
|
118
|
-
verbose=verbose,
|
|
119
|
-
output_pydantic=AutoIncludeOutput
|
|
120
|
-
)
|
|
121
|
-
total_cost += extract_response["cost"]
|
|
122
|
-
model_name = extract_response["model_name"]
|
|
123
|
-
|
|
124
|
-
if verbose:
|
|
125
|
-
console.print(Panel("Step 5: Extracting dependencies", style="blue"))
|
|
126
|
-
|
|
127
|
-
# Extract dependencies
|
|
128
|
-
dependencies = extract_response["result"].string_of_includes
|
|
129
|
-
except Exception as e:
|
|
130
|
-
console.print(f"[red]Error extracting dependencies: {str(e)}[/red]")
|
|
131
|
-
dependencies = ""
|
|
170
|
+
|
|
171
|
+
total_cost = summary_cost + llm_cost
|
|
172
|
+
model_name = llm_model_name or summary_model
|
|
132
173
|
|
|
133
174
|
if verbose:
|
|
134
|
-
console.print(Panel(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
175
|
+
console.print(Panel(
|
|
176
|
+
(
|
|
177
|
+
f"Results:\n"
|
|
178
|
+
f"Dependencies: {dependencies}\n"
|
|
179
|
+
f"CSV Output: {csv_output}\n"
|
|
180
|
+
f"Total Cost: ${total_cost:.6f}\n"
|
|
181
|
+
f"Model Used: {model_name}"
|
|
182
|
+
),
|
|
183
|
+
style="green"
|
|
184
|
+
))
|
|
141
185
|
|
|
142
186
|
return dependencies, csv_output, total_cost, model_name
|
|
143
187
|
|
|
144
|
-
except Exception as
|
|
145
|
-
console.print(f"[red]Error in auto_include: {str(
|
|
188
|
+
except Exception as ex:
|
|
189
|
+
console.print(f"[red]Error in auto_include: {str(ex)}[/red]")
|
|
146
190
|
raise
|
|
147
191
|
|
|
192
|
+
|
|
148
193
|
def main():
|
|
149
194
|
"""Example usage of auto_include function"""
|
|
150
195
|
try:
|
|
151
196
|
# Example inputs
|
|
152
197
|
input_prompt = "Write a function to process image data"
|
|
153
198
|
directory_path = "context/c*.py"
|
|
154
|
-
csv_file =
|
|
155
|
-
|
|
199
|
+
csv_file = (
|
|
200
|
+
"full_path,file_summary,date\n"
|
|
201
|
+
"context/image_utils.py,"
|
|
202
|
+
"\"Image processing utilities\",2023-01-01T10:00:00"
|
|
203
|
+
)
|
|
156
204
|
|
|
157
|
-
dependencies,
|
|
205
|
+
dependencies, _, total_cost, model_name = auto_include(
|
|
158
206
|
input_prompt=input_prompt,
|
|
159
207
|
directory_path=directory_path,
|
|
160
208
|
csv_file=csv_file,
|
|
161
209
|
strength=0.7,
|
|
162
210
|
temperature=0.0,
|
|
211
|
+
time=DEFAULT_TIME,
|
|
163
212
|
verbose=True
|
|
164
213
|
)
|
|
165
214
|
|
|
@@ -168,8 +217,8 @@ context/image_utils.py,"Image processing utilities",2023-01-01T10:00:00"""
|
|
|
168
217
|
console.print(f"Total Cost: ${total_cost:.6f}")
|
|
169
218
|
console.print(f"Model Used: {model_name}")
|
|
170
219
|
|
|
171
|
-
except Exception as
|
|
172
|
-
console.print(f"[red]Error in main: {str(
|
|
220
|
+
except Exception as ex:
|
|
221
|
+
console.print(f"[red]Error in main: {str(ex)}[/red]")
|
|
173
222
|
|
|
174
223
|
if __name__ == "__main__":
|
|
175
224
|
main()
|
pdd/auto_update.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"""This module provides a function to automatically update the package."""
|
|
1
2
|
import importlib.metadata
|
|
2
3
|
import requests
|
|
3
4
|
import semver
|
|
@@ -63,11 +64,11 @@ def auto_update(package_name: str = "pdd-cli", latest_version: str = None) -> No
|
|
|
63
64
|
if latest_version is None:
|
|
64
65
|
try:
|
|
65
66
|
pypi_url = f"https://pypi.org/pypi/{package_name}/json"
|
|
66
|
-
response = requests.get(pypi_url)
|
|
67
|
+
response = requests.get(pypi_url, timeout=10)
|
|
67
68
|
response.raise_for_status()
|
|
68
69
|
latest_version = response.json()['info']['version']
|
|
69
|
-
except Exception as
|
|
70
|
-
print(f"Failed to fetch latest version from PyPI: {str(
|
|
70
|
+
except Exception as ex:
|
|
71
|
+
print(f"Failed to fetch latest version from PyPI: {str(ex)}")
|
|
71
72
|
return
|
|
72
73
|
|
|
73
74
|
# Compare versions using semantic versioning
|
|
@@ -99,7 +100,13 @@ def auto_update(package_name: str = "pdd-cli", latest_version: str = None) -> No
|
|
|
99
100
|
print(f"Upgrading with command: {cmd_str}")
|
|
100
101
|
|
|
101
102
|
try:
|
|
102
|
-
result = subprocess.run(
|
|
103
|
+
result = subprocess.run(
|
|
104
|
+
cmd,
|
|
105
|
+
shell=use_shell,
|
|
106
|
+
capture_output=True,
|
|
107
|
+
text=True,
|
|
108
|
+
check=False
|
|
109
|
+
)
|
|
103
110
|
|
|
104
111
|
if result.returncode == 0:
|
|
105
112
|
print(f"\nSuccessfully upgraded {package_name} to version {latest_version}")
|
|
@@ -114,15 +121,21 @@ def auto_update(package_name: str = "pdd-cli", latest_version: str = None) -> No
|
|
|
114
121
|
print(f"Fallback command: {fallback_str}")
|
|
115
122
|
|
|
116
123
|
try:
|
|
117
|
-
fallback_result = subprocess.run(
|
|
124
|
+
fallback_result = subprocess.run(
|
|
125
|
+
fallback_cmd,
|
|
126
|
+
shell=fallback_shell,
|
|
127
|
+
capture_output=True,
|
|
128
|
+
text=True,
|
|
129
|
+
check=False
|
|
130
|
+
)
|
|
118
131
|
if fallback_result.returncode == 0:
|
|
119
132
|
print(f"\nSuccessfully upgraded {package_name} using fallback method")
|
|
120
133
|
else:
|
|
121
134
|
print(f"\nFallback upgrade failed: {fallback_result.stderr}")
|
|
122
|
-
except Exception as
|
|
123
|
-
print(f"\nError during fallback upgrade: {str(
|
|
124
|
-
except Exception as
|
|
125
|
-
print(f"\nError during upgrade: {str(
|
|
135
|
+
except Exception as fallback_ex:
|
|
136
|
+
print(f"\nError during fallback upgrade: {str(fallback_ex)}")
|
|
137
|
+
except Exception as ex:
|
|
138
|
+
print(f"\nError during upgrade: {str(ex)}")
|
|
126
139
|
break
|
|
127
140
|
elif response in ['n', 'no', '']:
|
|
128
141
|
print("\nUpgrade cancelled")
|
|
@@ -132,8 +145,8 @@ def auto_update(package_name: str = "pdd-cli", latest_version: str = None) -> No
|
|
|
132
145
|
|
|
133
146
|
except importlib.metadata.PackageNotFoundError:
|
|
134
147
|
print(f"Package {package_name} is not installed")
|
|
135
|
-
except Exception as
|
|
136
|
-
print(f"Error checking for updates: {str(
|
|
148
|
+
except Exception as ex:
|
|
149
|
+
print(f"Error checking for updates: {str(ex)}")
|
|
137
150
|
|
|
138
151
|
|
|
139
152
|
if __name__ == "__main__":
|
pdd/bug_main.py
CHANGED
|
@@ -5,6 +5,7 @@ import click
|
|
|
5
5
|
from rich import print as rprint
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
|
+
from . import DEFAULT_STRENGTH, DEFAULT_TIME
|
|
8
9
|
from .construct_paths import construct_paths
|
|
9
10
|
from .bug_to_unit_test import bug_to_unit_test
|
|
10
11
|
|
|
@@ -64,8 +65,9 @@ def bug_main(
|
|
|
64
65
|
desired_output_content = input_strings["desired_output"]
|
|
65
66
|
|
|
66
67
|
# Generate unit test
|
|
67
|
-
strength = ctx.obj.get('strength',
|
|
68
|
+
strength = ctx.obj.get('strength', DEFAULT_STRENGTH)
|
|
68
69
|
temperature = ctx.obj.get('temperature', 0)
|
|
70
|
+
time_budget = ctx.obj.get('time', DEFAULT_TIME)
|
|
69
71
|
unit_test, total_cost, model_name = bug_to_unit_test(
|
|
70
72
|
current_output_content,
|
|
71
73
|
desired_output_content,
|
|
@@ -74,7 +76,8 @@ def bug_main(
|
|
|
74
76
|
program_content,
|
|
75
77
|
strength,
|
|
76
78
|
temperature,
|
|
77
|
-
language
|
|
79
|
+
language,
|
|
80
|
+
time_budget
|
|
78
81
|
)
|
|
79
82
|
|
|
80
83
|
# Save results if output path is provided
|
pdd/bug_to_unit_test.py
CHANGED
|
@@ -2,7 +2,7 @@ from typing import Tuple, Optional
|
|
|
2
2
|
from rich import print
|
|
3
3
|
from rich.markdown import Markdown
|
|
4
4
|
from rich.console import Console
|
|
5
|
-
from . import EXTRACTION_STRENGTH, DEFAULT_STRENGTH
|
|
5
|
+
from . import EXTRACTION_STRENGTH, DEFAULT_STRENGTH, DEFAULT_TIME
|
|
6
6
|
from .load_prompt_template import load_prompt_template
|
|
7
7
|
from .llm_invoke import llm_invoke
|
|
8
8
|
from .unfinished_prompt import unfinished_prompt
|
|
@@ -20,6 +20,7 @@ def bug_to_unit_test(
|
|
|
20
20
|
program_used_to_run_code_under_test: str,
|
|
21
21
|
strength: float = DEFAULT_STRENGTH,
|
|
22
22
|
temperature: float = 0.0,
|
|
23
|
+
time: float = DEFAULT_TIME,
|
|
23
24
|
language: str = "python"
|
|
24
25
|
) -> Tuple[str, float, str]:
|
|
25
26
|
"""
|
|
@@ -33,6 +34,7 @@ def bug_to_unit_test(
|
|
|
33
34
|
program_used_to_run_code_under_test (str): Program used to run the code
|
|
34
35
|
strength (float, optional): Strength of the LLM model. Must be between 0 and 1. Defaults to DEFAULT_STRENGTH.
|
|
35
36
|
temperature (float, optional): Temperature of the LLM model. Defaults to 0.0.
|
|
37
|
+
time (float, optional): Time budget for LLM calls. Defaults to DEFAULT_TIME.
|
|
36
38
|
language (str, optional): Programming language. Defaults to "python".
|
|
37
39
|
|
|
38
40
|
Returns:
|
|
@@ -77,6 +79,7 @@ def bug_to_unit_test(
|
|
|
77
79
|
input_json=input_json,
|
|
78
80
|
strength=strength,
|
|
79
81
|
temperature=temperature,
|
|
82
|
+
time=time,
|
|
80
83
|
verbose=True
|
|
81
84
|
)
|
|
82
85
|
|
|
@@ -93,6 +96,7 @@ def bug_to_unit_test(
|
|
|
93
96
|
prompt_text=last_600_chars,
|
|
94
97
|
strength=0.75,
|
|
95
98
|
temperature=temperature,
|
|
99
|
+
time=time,
|
|
96
100
|
verbose=False
|
|
97
101
|
)
|
|
98
102
|
|
|
@@ -105,6 +109,7 @@ def bug_to_unit_test(
|
|
|
105
109
|
llm_output=response['result'],
|
|
106
110
|
strength=strength,
|
|
107
111
|
temperature=temperature,
|
|
112
|
+
time=time,
|
|
108
113
|
verbose=True
|
|
109
114
|
)
|
|
110
115
|
total_cost += continued_cost
|
|
@@ -124,6 +129,7 @@ def bug_to_unit_test(
|
|
|
124
129
|
language,
|
|
125
130
|
strength=EXTRACTION_STRENGTH,
|
|
126
131
|
temperature=temperature,
|
|
132
|
+
time=time,
|
|
127
133
|
verbose=True
|
|
128
134
|
)
|
|
129
135
|
total_cost += postprocess_cost
|
|
@@ -154,7 +160,8 @@ def add_numbers(a, b):
|
|
|
154
160
|
desired_output=desired_output,
|
|
155
161
|
prompt_used_to_generate_the_code=prompt,
|
|
156
162
|
code_under_test=code,
|
|
157
|
-
program_used_to_run_code_under_test=program
|
|
163
|
+
program_used_to_run_code_under_test=program,
|
|
164
|
+
time=DEFAULT_TIME
|
|
158
165
|
)
|
|
159
166
|
|
|
160
167
|
if unit_test:
|