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.

Files changed (50) hide show
  1. pdd/__init__.py +5 -4
  2. pdd/auto_deps_main.py +14 -7
  3. pdd/auto_include.py +147 -98
  4. pdd/auto_update.py +24 -11
  5. pdd/bug_main.py +5 -2
  6. pdd/bug_to_unit_test.py +9 -2
  7. pdd/change.py +32 -22
  8. pdd/change_main.py +14 -10
  9. pdd/cli.py +11 -1
  10. pdd/cmd_test_main.py +7 -3
  11. pdd/code_generator.py +7 -1
  12. pdd/code_generator_main.py +9 -3
  13. pdd/conflicts_in_prompts.py +7 -2
  14. pdd/conflicts_main.py +6 -2
  15. pdd/context_generator.py +20 -3
  16. pdd/context_generator_main.py +2 -0
  17. pdd/continue_generation.py +8 -2
  18. pdd/crash_main.py +51 -31
  19. pdd/detect_change.py +8 -4
  20. pdd/detect_change_main.py +3 -0
  21. pdd/fix_code_loop.py +7 -2
  22. pdd/fix_code_module_errors.py +5 -2
  23. pdd/fix_error_loop.py +6 -2
  24. pdd/fix_errors_from_unit_tests.py +11 -6
  25. pdd/fix_main.py +4 -0
  26. pdd/fix_verification_errors.py +8 -3
  27. pdd/fix_verification_errors_loop.py +9 -3
  28. pdd/fix_verification_main.py +37 -31
  29. pdd/generate_test.py +10 -4
  30. pdd/get_extension.py +23 -9
  31. pdd/git_update.py +5 -3
  32. pdd/increase_tests.py +5 -2
  33. pdd/insert_includes.py +8 -2
  34. pdd/preprocess_main.py +10 -3
  35. pdd/process_csv_change.py +8 -2
  36. pdd/split.py +15 -7
  37. pdd/split_main.py +2 -0
  38. pdd/summarize_directory.py +4 -0
  39. pdd/trace.py +9 -5
  40. pdd/trace_main.py +5 -4
  41. pdd/unfinished_prompt.py +6 -1
  42. pdd/update_main.py +6 -3
  43. pdd/update_prompt.py +8 -4
  44. pdd/xml_tagger.py +10 -5
  45. {pdd_cli-0.0.38.dist-info → pdd_cli-0.0.40.dist-info}/METADATA +4 -4
  46. {pdd_cli-0.0.38.dist-info → pdd_cli-0.0.40.dist-info}/RECORD +50 -50
  47. {pdd_cli-0.0.38.dist-info → pdd_cli-0.0.40.dist-info}/WHEEL +0 -0
  48. {pdd_cli-0.0.38.dist-info → pdd_cli-0.0.40.dist-info}/entry_points.txt +0 -0
  49. {pdd_cli-0.0.38.dist-info → pdd_cli-0.0.40.dist-info}/licenses/LICENSE +0 -0
  50. {pdd_cli-0.0.38.dist-info → pdd_cli-0.0.40.dist-info}/top_level.txt +0 -0
pdd/crash_main.py CHANGED
@@ -2,7 +2,7 @@ import sys
2
2
  from typing import Tuple, Optional, Dict, Any
3
3
  import click
4
4
  from rich import print as rprint
5
- from . import DEFAULT_STRENGTH
5
+ from . import DEFAULT_STRENGTH, DEFAULT_TIME
6
6
  from pathlib import Path
7
7
 
8
8
  from .construct_paths import construct_paths
@@ -54,6 +54,11 @@ def crash_main(
54
54
  quiet = ctx.params.get("quiet", ctx.obj.get("quiet", False))
55
55
  verbose = ctx.params.get("verbose", ctx.obj.get("verbose", False)) # Get verbose flag
56
56
 
57
+ # Get model parameters from context early, including time
58
+ strength = ctx.obj.get("strength", DEFAULT_STRENGTH)
59
+ temperature = ctx.obj.get("temperature", 0)
60
+ time_param = ctx.obj.get("time", DEFAULT_TIME) # Renamed from time_budget for clarity
61
+
57
62
  try:
58
63
  # Construct file paths
59
64
  input_file_paths = {
@@ -84,71 +89,86 @@ def crash_main(
84
89
  program_content = input_strings["program_file"]
85
90
  error_content = input_strings["error_file"]
86
91
 
87
- # Get model parameters from context
88
- strength = ctx.obj.get("strength", DEFAULT_STRENGTH)
89
- temperature = ctx.obj.get("temperature", 0)
92
+ # Store original content for comparison later
93
+ original_code_content = code_content
94
+ original_program_content = program_content
95
+
96
+ # Get model parameters from context (strength, temperature, time already fetched)
97
+ # strength = ctx.obj.get("strength", DEFAULT_STRENGTH) # Moved up
98
+ # temperature = ctx.obj.get("temperature", 0) # Moved up
99
+ # time_budget = ctx.obj.get("time", DEFAULT_TIME) # Moved up and renamed
90
100
 
91
101
  # verbose = ctx.params.get("verbose", ctx.obj.get("verbose", False)) # Already defined above
92
102
 
103
+ code_updated: bool = False
104
+ program_updated: bool = False
105
+
93
106
  if loop:
94
107
  # Use iterative fixing process
108
+ # Corrected parameter order for fix_code_loop, adding time_param
95
109
  success, final_program, final_code, attempts, cost, model = fix_code_loop(
96
- code_file, prompt_content, program_file, strength, temperature, max_attempts or 3, budget or 5.0, error_file, verbose
110
+ code_file, prompt_content, program_file, strength, temperature,
111
+ max_attempts or 3, budget or 5.0, error_file, verbose, time_param
97
112
  )
113
+ # Determine if content was updated by fix_code_loop
114
+ if success: # Only consider updates if the loop reported success
115
+ code_updated = bool(final_code and final_code != original_code_content)
116
+ program_updated = bool(final_program and final_program != original_program_content)
98
117
  else:
99
118
  # Use single fix attempt
100
119
  if fix_code_module_errors is None:
101
120
  raise ImportError("fix_code_module_errors is required but not available.")
102
- # Note: fix_code_module_errors returns 7 values according to example
103
- # update_program, update_code, fixed_program, fixed_code, program_code_fix, cost, model
104
- # The current code unpacks 7 values, which matches the example.
105
- update_program, update_code, final_program, final_code, program_code_fix, cost, model = fix_code_module_errors(
106
- program_content, prompt_content, code_content, error_content, strength, temperature, verbose
121
+ # Corrected parameter order for fix_code_module_errors, adding time_param
122
+ fm_update_program, fm_update_code, final_program, final_code, program_code_fix, cost, model = fix_code_module_errors(
123
+ program_content, prompt_content, code_content, error_content, strength, temperature, verbose, time_param
107
124
  )
108
125
  success = True # Assume success after one attempt if no exception
109
126
  attempts = 1
127
+ # Use boolean flags from fix_code_module_errors and ensure content is not empty
128
+ code_updated = fm_update_code and bool(final_code)
129
+ program_updated = fm_update_program and bool(final_program)
110
130
 
111
- # Ensure we have content to write, falling back to original content if needed
112
- if final_program == "":
113
- final_program = program_content
131
+ # Removed fallback to original content if final_code/final_program are empty
132
+ # An empty string from a fix function means no valid update.
114
133
 
115
- if final_code == "":
116
- final_code = code_content
117
-
118
- # Determine whether to write the files based on whether paths are provided
134
+ # Determine whether to write the files based on whether paths are provided AND content was updated
119
135
  output_code_path_str = output_file_paths.get("output")
120
136
  output_program_path_str = output_file_paths.get("output_program")
121
137
 
122
- should_write_code = output_code_path_str is not None
123
- should_write_program = output_program_path_str is not None
124
-
125
- # Write output files
126
- if should_write_code:
138
+ # Write output files only if updated and path provided
139
+ if output_code_path_str and code_updated:
127
140
  output_code_path = Path(output_code_path_str)
128
141
  output_code_path.parent.mkdir(parents=True, exist_ok=True) # Ensure directory exists
129
142
  with open(output_code_path, "w") as f:
130
143
  f.write(final_code)
131
144
 
132
- if should_write_program:
145
+ if output_program_path_str and program_updated:
133
146
  output_program_path = Path(output_program_path_str)
134
147
  output_program_path.parent.mkdir(parents=True, exist_ok=True) # Ensure directory exists
135
148
  with open(output_program_path, "w") as f:
136
149
  f.write(final_program)
137
150
 
138
- # Provide user feedback (using quiet flag as per current implementation)
139
- # To strictly follow the prompt's last note, change 'if not quiet:' to 'if verbose:'
151
+ # Provide user feedback
140
152
  if not quiet:
141
153
  if success:
142
- rprint("[bold green]Crash fix completed successfully.[/bold green]")
154
+ rprint("[bold green]Crash fix attempt completed.[/bold green]") # Changed message slightly
143
155
  else:
144
- rprint("[bold yellow]Crash fix completed with issues.[/bold yellow]")
156
+ rprint("[bold yellow]Crash fix attempt completed with issues or no changes made.[/bold yellow]") # Changed message
145
157
  rprint(f"[bold]Model used:[/bold] {model}")
146
158
  rprint(f"[bold]Total attempts:[/bold] {attempts}")
147
159
  rprint(f"[bold]Total cost:[/bold] ${cost:.2f}")
148
- if should_write_code:
149
- rprint(f"[bold]Fixed code saved to:[/bold] {output_code_path_str}")
150
- if should_write_program:
151
- rprint(f"[bold]Fixed program saved to:[/bold] {output_program_path_str}")
160
+
161
+ if output_code_path_str:
162
+ if code_updated:
163
+ rprint(f"[bold]Fixed code saved to:[/bold] {output_code_path_str}")
164
+ else:
165
+ rprint(f"[info]Code file {Path(code_file).name} was not modified. Output file {output_code_path_str} not written.[/info]")
166
+
167
+ if output_program_path_str:
168
+ if program_updated:
169
+ rprint(f"[bold]Fixed program saved to:[/bold] {output_program_path_str}")
170
+ else:
171
+ rprint(f"[info]Program file {Path(program_file).name} was not modified. Output file {output_program_path_str} not written.[/info]")
152
172
 
153
173
  return success, final_code, final_program, attempts, cost, model
154
174
 
pdd/detect_change.py CHANGED
@@ -1,9 +1,9 @@
1
- from typing import List, Dict, Tuple
1
+ from typing import List, Dict, Tuple, Optional
2
2
  from pathlib import Path
3
3
  from rich.console import Console
4
4
  from rich.markdown import Markdown
5
5
  from pydantic import BaseModel, Field
6
- from . import EXTRACTION_STRENGTH
6
+ from . import EXTRACTION_STRENGTH, DEFAULT_STRENGTH, DEFAULT_TIME
7
7
 
8
8
  from .preprocess import preprocess
9
9
  from .load_prompt_template import load_prompt_template
@@ -21,8 +21,9 @@ class ChangesList(BaseModel):
21
21
  def detect_change(
22
22
  prompt_files: List[str],
23
23
  change_description: str,
24
- strength: float,
25
- temperature: float,
24
+ strength: float=DEFAULT_STRENGTH,
25
+ temperature: float=0.0,
26
+ time: Optional[float] = DEFAULT_TIME,
26
27
  verbose: bool = False
27
28
  ) -> Tuple[List[Dict[str, str]], float, str]:
28
29
  """
@@ -33,6 +34,7 @@ def detect_change(
33
34
  change_description (str): Description of the changes to analyze
34
35
  strength (float): Strength parameter for the LLM model
35
36
  temperature (float): Temperature parameter for the LLM model
37
+ time (float): Time budget for LLM calls.
36
38
  verbose (bool): Whether to print detailed information
37
39
 
38
40
  Returns:
@@ -87,6 +89,7 @@ def detect_change(
87
89
  },
88
90
  strength=strength,
89
91
  temperature=temperature,
92
+ time=time,
90
93
  verbose=verbose
91
94
  )
92
95
 
@@ -104,6 +107,7 @@ def detect_change(
104
107
  input_json={"llm_output": detect_response['result']},
105
108
  strength=EXTRACTION_STRENGTH,
106
109
  temperature=0.0,
110
+ time=time,
107
111
  verbose=verbose,
108
112
  output_pydantic=ChangesList
109
113
  )
pdd/detect_change_main.py CHANGED
@@ -6,6 +6,7 @@ from rich import print as rprint
6
6
 
7
7
  from .construct_paths import construct_paths
8
8
  from .detect_change import detect_change
9
+ from . import DEFAULT_TIME
9
10
 
10
11
  def detect_change_main(
11
12
  ctx: click.Context,
@@ -55,6 +56,7 @@ def detect_change_main(
55
56
  # Get model parameters from context
56
57
  strength = ctx.obj.get('strength', 0.9)
57
58
  temperature = ctx.obj.get('temperature', 0)
59
+ time_budget = ctx.obj.get('time', DEFAULT_TIME)
58
60
 
59
61
  # Analyze which prompts need changes
60
62
  changes_list, total_cost, model_name = detect_change(
@@ -62,6 +64,7 @@ def detect_change_main(
62
64
  change_description,
63
65
  strength,
64
66
  temperature,
67
+ time_budget,
65
68
  verbose=not ctx.obj.get('quiet', False)
66
69
  )
67
70
 
pdd/fix_code_loop.py CHANGED
@@ -4,6 +4,7 @@ import subprocess
4
4
  import sys
5
5
  from pathlib import Path
6
6
  from typing import Tuple
7
+ from . import DEFAULT_TIME # Added DEFAULT_TIME
7
8
 
8
9
  # Use Rich for pretty printing to the console
9
10
  from rich.console import Console
@@ -25,6 +26,7 @@ except ImportError:
25
26
  # sys.path.append(str(Path(__file__).parent.parent)) # Adjust based on structure
26
27
  from fix_code_module_errors import fix_code_module_errors
27
28
 
29
+
28
30
  def fix_code_loop(
29
31
  code_file: str,
30
32
  prompt: str,
@@ -33,8 +35,9 @@ def fix_code_loop(
33
35
  temperature: float,
34
36
  max_attempts: int,
35
37
  budget: float,
36
- error_log_file: str = "error_code.log",
38
+ error_log_file: str,
37
39
  verbose: bool = False,
40
+ time: float = DEFAULT_TIME,
38
41
  ) -> Tuple[bool, str, str, int, float, str | None]:
39
42
  """
40
43
  Attempts to fix errors in a code module through multiple iterations.
@@ -47,8 +50,9 @@ def fix_code_loop(
47
50
  temperature: LLM temperature (0.0 to 1.0).
48
51
  max_attempts: Maximum number of fix attempts.
49
52
  budget: Maximum cost allowed for the fixing process.
50
- error_log_file: Path to the error log file (default: "error_code.log").
53
+ error_log_file: Path to the error log file.
51
54
  verbose: Enable detailed logging (default: False).
55
+ time: Time limit for the LLM calls (default: DEFAULT_TIME).
52
56
 
53
57
  Returns:
54
58
  Tuple containing the following in order:
@@ -219,6 +223,7 @@ def fix_code_loop(
219
223
  errors=error_context_for_llm, # Pass the structured history
220
224
  strength=strength,
221
225
  temperature=temperature,
226
+ time=time, # Pass time
222
227
  verbose=verbose,
223
228
  )
224
229
  if model_name_iter:
@@ -4,7 +4,7 @@ from rich import print
4
4
  from rich.markdown import Markdown
5
5
  from .load_prompt_template import load_prompt_template
6
6
  from .llm_invoke import llm_invoke
7
- from . import EXTRACTION_STRENGTH
7
+ from . import EXTRACTION_STRENGTH, DEFAULT_TIME, DEFAULT_STRENGTH
8
8
  import json
9
9
 
10
10
  class CodeFix(BaseModel):
@@ -35,8 +35,9 @@ def fix_code_module_errors(
35
35
  prompt: str,
36
36
  code: str,
37
37
  errors: str,
38
- strength: float,
38
+ strength: float = DEFAULT_STRENGTH,
39
39
  temperature: float = 0,
40
+ time: float = DEFAULT_TIME,
40
41
  verbose: bool = False
41
42
  ) -> Tuple[bool, bool, str, str, str, float, str]:
42
43
  """
@@ -72,6 +73,7 @@ def fix_code_module_errors(
72
73
  input_json=input_json,
73
74
  strength=strength,
74
75
  temperature=temperature,
76
+ time=time,
75
77
  verbose=verbose
76
78
  )
77
79
 
@@ -99,6 +101,7 @@ def fix_code_module_errors(
99
101
  input_json=extract_input,
100
102
  strength=EXTRACTION_STRENGTH, # Fixed strength for extraction
101
103
  temperature=temperature,
104
+ time=time,
102
105
  verbose=verbose,
103
106
  output_pydantic=CodeFix
104
107
  )
pdd/fix_error_loop.py CHANGED
@@ -11,6 +11,7 @@ from rich.console import Console
11
11
 
12
12
  # Relative import from an internal module.
13
13
  from .fix_errors_from_unit_tests import fix_errors_from_unit_tests
14
+ from . import DEFAULT_TIME # Import DEFAULT_TIME
14
15
 
15
16
  console = Console()
16
17
 
@@ -104,7 +105,8 @@ def fix_error_loop(unit_test_file: str,
104
105
  max_attempts: int,
105
106
  budget: float,
106
107
  error_log_file: str = "error_log.txt",
107
- verbose: bool = False):
108
+ verbose: bool = False,
109
+ time: float = DEFAULT_TIME):
108
110
  """
109
111
  Attempt to fix errors in a unit test and corresponding code using repeated iterations,
110
112
  counting only the number of times we actually call the LLM fix function.
@@ -124,6 +126,7 @@ def fix_error_loop(unit_test_file: str,
124
126
  budget: Maximum cost allowed for the fixing process.
125
127
  error_log_file: Path to file to log errors (default: "error_log.txt").
126
128
  verbose: Enable verbose logging (default: False).
129
+ time: Time parameter for the fix_errors_from_unit_tests call.
127
130
 
128
131
  Outputs:
129
132
  success: Boolean indicating if the overall process succeeded.
@@ -331,7 +334,8 @@ def fix_error_loop(unit_test_file: str,
331
334
  error_log_file,
332
335
  strength,
333
336
  temperature,
334
- verbose=verbose
337
+ verbose=verbose,
338
+ time=time # Pass time parameter
335
339
  )
336
340
 
337
341
  # Update the fix attempt in the structured log
@@ -10,6 +10,7 @@ from rich.panel import Panel
10
10
  from tempfile import NamedTemporaryFile
11
11
 
12
12
  from . import DEFAULT_STRENGTH
13
+ from . import DEFAULT_TIME, EXTRACTION_STRENGTH
13
14
  from .preprocess import preprocess
14
15
  from .load_prompt_template import load_prompt_template
15
16
  from .llm_invoke import llm_invoke
@@ -104,9 +105,10 @@ def fix_errors_from_unit_tests(
104
105
  prompt: str,
105
106
  error: str,
106
107
  error_file: str,
107
- strength: float,
108
- temperature: float,
109
- verbose: bool = False
108
+ strength: float = DEFAULT_STRENGTH,
109
+ temperature: float = 0.0,
110
+ verbose: bool = False,
111
+ time: float = DEFAULT_TIME
110
112
  ) -> Tuple[bool, bool, str, str, str, float, str]:
111
113
  """
112
114
  Fix errors in unit tests using LLM models and log the process.
@@ -120,6 +122,7 @@ def fix_errors_from_unit_tests(
120
122
  strength (float): LLM model strength (0-1)
121
123
  temperature (float): LLM temperature (0-1)
122
124
  verbose (bool): Whether to print detailed output
125
+ time (float): Time parameter for llm_invoke
123
126
 
124
127
  Returns:
125
128
  Tuple containing update flags, fixed code/tests, total cost, and model name
@@ -178,7 +181,8 @@ def fix_errors_from_unit_tests(
178
181
  },
179
182
  strength=strength,
180
183
  temperature=temperature,
181
- verbose=verbose
184
+ verbose=verbose,
185
+ time=time
182
186
  )
183
187
 
184
188
  total_cost += response1['cost']
@@ -211,10 +215,11 @@ def fix_errors_from_unit_tests(
211
215
  "unit_test": unit_test,
212
216
  "code": code
213
217
  },
214
- strength=DEFAULT_STRENGTH, # Fixed strength as per requirements
218
+ strength=EXTRACTION_STRENGTH, # Fixed strength as per requirements
215
219
  temperature=temperature,
216
220
  output_pydantic=CodeFix,
217
- verbose=verbose
221
+ verbose=verbose,
222
+ time=time
218
223
  )
219
224
 
220
225
  total_cost += response2['cost']
pdd/fix_main.py CHANGED
@@ -104,6 +104,8 @@ def fix_main(
104
104
  strength = ctx.obj.get('strength', DEFAULT_STRENGTH)
105
105
  temperature = ctx.obj.get('temperature', 0)
106
106
  verbose = ctx.obj.get('verbose', False)
107
+ time = ctx.obj.get('time') # Get time from context
108
+
107
109
  if loop:
108
110
  # Use fix_error_loop for iterative fixing
109
111
  success, fixed_unit_test, fixed_code, attempts, total_cost, model_name = fix_error_loop(
@@ -113,6 +115,7 @@ def fix_main(
113
115
  verification_program=verification_program,
114
116
  strength=strength,
115
117
  temperature=temperature,
118
+ time=time, # Pass time to fix_error_loop
116
119
  max_attempts=max_attempts,
117
120
  budget=budget,
118
121
  error_log_file=output_file_paths.get("output_results"),
@@ -128,6 +131,7 @@ def fix_main(
128
131
  error_file=output_file_paths.get("output_results"),
129
132
  strength=strength,
130
133
  temperature=temperature,
134
+ time=time, # Pass time to fix_errors_from_unit_tests
131
135
  verbose=verbose
132
136
  )
133
137
  success = update_unit_test or update_code
@@ -5,6 +5,7 @@ from rich.markdown import Markdown
5
5
  from pydantic import BaseModel, Field
6
6
  from .load_prompt_template import load_prompt_template
7
7
  from .llm_invoke import llm_invoke
8
+ from . import DEFAULT_TIME, DEFAULT_STRENGTH # Import defaults
8
9
 
9
10
  # Define Pydantic model for structured LLM output for VERIFICATION
10
11
  class VerificationOutput(BaseModel):
@@ -22,9 +23,10 @@ def fix_verification_errors(
22
23
  prompt: str,
23
24
  code: str,
24
25
  output: str,
25
- strength: float,
26
+ strength: float = DEFAULT_STRENGTH,
26
27
  temperature: float = 0.0,
27
28
  verbose: bool = False,
29
+ time: float = DEFAULT_TIME
28
30
  ) -> Dict[str, Any]:
29
31
  """
30
32
  Identifies and fixes issues in a code module based on verification output.
@@ -37,6 +39,7 @@ def fix_verification_errors(
37
39
  strength: The strength (0-1) for the LLM model selection.
38
40
  temperature: The temperature for the LLM model. Defaults to 0.
39
41
  verbose: If True, prints detailed execution information. Defaults to False.
42
+ time: The time for the LLM model. Defaults to DEFAULT_TIME.
40
43
 
41
44
  Returns:
42
45
  A dictionary containing:
@@ -116,7 +119,8 @@ def fix_verification_errors(
116
119
  strength=strength,
117
120
  temperature=temperature,
118
121
  verbose=False,
119
- output_pydantic=VerificationOutput
122
+ output_pydantic=VerificationOutput,
123
+ time=time
120
124
  )
121
125
  total_cost += verification_response.get('cost', 0.0)
122
126
  model_name = verification_response.get('model_name', model_name)
@@ -246,7 +250,8 @@ def fix_verification_errors(
246
250
  strength=strength,
247
251
  temperature=temperature,
248
252
  verbose=False,
249
- output_pydantic=FixerOutput
253
+ output_pydantic=FixerOutput,
254
+ time=time
250
255
  )
251
256
  total_cost += fix_response.get('cost', 0.0)
252
257
  model_name = fix_response.get('model_name', model_name)
@@ -2,10 +2,10 @@ import os
2
2
  import shutil
3
3
  import subprocess
4
4
  import datetime
5
- import time
6
5
  from pathlib import Path
7
6
  from typing import Dict, Tuple, Any, Optional
8
7
  from xml.sax.saxutils import escape
8
+ import time
9
9
 
10
10
  from rich.console import Console
11
11
 
@@ -24,6 +24,8 @@ except ImportError:
24
24
  "Ensure it's available via relative import or in the 'pdd' package."
25
25
  )
26
26
 
27
+ from . import DEFAULT_TIME # Import DEFAULT_TIME
28
+
27
29
  # Initialize Rich Console for pretty printing
28
30
  console = Console()
29
31
 
@@ -90,6 +92,7 @@ def fix_verification_errors_loop(
90
92
  output_program_path: Optional[str] = None,
91
93
  verbose: bool = False,
92
94
  program_args: Optional[list[str]] = None,
95
+ llm_time: float = DEFAULT_TIME # Add time parameter
93
96
  ) -> Dict[str, Any]:
94
97
  """
95
98
  Attempts to fix errors in a code file based on program execution output
@@ -109,6 +112,7 @@ def fix_verification_errors_loop(
109
112
  output_program_path: Optional path to save fixed program (default: None).
110
113
  verbose: Enable verbose logging (default: False).
111
114
  program_args: Optional list of command-line arguments for the program_file.
115
+ llm_time: Time parameter for fix_verification_errors calls (default: DEFAULT_TIME).
112
116
 
113
117
  Returns:
114
118
  A dictionary containing:
@@ -227,7 +231,8 @@ def fix_verification_errors_loop(
227
231
  output=initial_output,
228
232
  strength=strength,
229
233
  temperature=temperature,
230
- verbose=verbose
234
+ verbose=verbose,
235
+ time=llm_time # Pass time
231
236
  )
232
237
  # 3e: Add cost
233
238
  initial_cost = initial_fix_result.get('total_cost', 0.0)
@@ -427,7 +432,8 @@ def fix_verification_errors_loop(
427
432
  output=program_output,
428
433
  strength=strength,
429
434
  temperature=temperature,
430
- verbose=verbose
435
+ verbose=verbose,
436
+ time=llm_time # Pass time
431
437
  )
432
438
 
433
439
  # 4f: Add cost
@@ -16,7 +16,7 @@ from .construct_paths import construct_paths
16
16
  from .fix_verification_errors import fix_verification_errors
17
17
  from .fix_verification_errors_loop import fix_verification_errors_loop
18
18
  # Import DEFAULT_STRENGTH from the main package
19
- from . import DEFAULT_STRENGTH
19
+ from . import DEFAULT_STRENGTH, DEFAULT_TIME
20
20
 
21
21
  # Default values from the README
22
22
  DEFAULT_TEMPERATURE = 0.0
@@ -135,6 +135,7 @@ def fix_verification_main(
135
135
  force: bool = ctx.obj.get('force', False)
136
136
  quiet: bool = ctx.obj.get('quiet', False)
137
137
  verbose: bool = ctx.obj.get('verbose', False)
138
+ time: float = ctx.obj.get('time', DEFAULT_TIME) # Get time from context, default 0.25
138
139
 
139
140
  # --- Input Validation ---
140
141
  if loop and not verification_program:
@@ -250,35 +251,39 @@ def fix_verification_main(
250
251
  try:
251
252
  if loop:
252
253
  if not quiet:
253
- rich_print("\n[bold blue]Running Iterative Verification (fix_verification_errors_loop)...[/bold blue]")
254
-
255
- # fix_verification_errors_loop handles file I/O internally
256
- # Pass file paths directly
257
- # TODO: How are program_args passed? Assuming empty list for now. Needs CLI option.
258
- program_args: List[str] = []
259
-
260
- loop_results = fix_verification_errors_loop(
261
- program_file=program_file,
262
- code_file=code_file,
263
- prompt=input_strings["prompt_file"],
264
- verification_program=verification_program,
265
- strength=strength,
266
- temperature=temperature,
267
- max_attempts=max_attempts,
268
- budget=budget,
269
- verification_log_file=output_results_path,
270
- verbose=verbose,
271
- program_args=program_args
272
- )
273
- success = loop_results['success']
274
- final_program = loop_results['final_program']
275
- final_code = loop_results['final_code']
276
- attempts = loop_results['total_attempts']
277
- total_cost = loop_results['total_cost']
278
- model_name = loop_results['model_name']
279
- # The loop function writes its own detailed log, so we don't need to build one here.
280
- # We just need to ensure the path was passed correctly.
281
-
254
+ rich_print("[dim]Running Iterative Verification (fix_verification_errors_loop)...[/dim]")
255
+ try:
256
+ # Call fix_verification_errors_loop for iterative fixing
257
+ loop_results = fix_verification_errors_loop(
258
+ program_file=program_file, # Changed to pass the program_file path
259
+ code_file=code_file, # Changed to pass the code_file path
260
+ prompt=input_strings["prompt_file"], # Correctly passing prompt content
261
+ verification_program=verification_program, # Path to the verifier program
262
+ strength=strength,
263
+ temperature=temperature,
264
+ llm_time=time, # Changed 'time' to 'llm_time'
265
+ max_attempts=max_attempts,
266
+ budget=budget,
267
+ verification_log_file=output_results_path, # Use resolved output_results_path
268
+ # output_code_path should not be passed here
269
+ # output_program_path should not be passed here
270
+ verbose=verbose,
271
+ program_args=[] # Pass an empty list for program_args
272
+ )
273
+ success = loop_results.get('success', False)
274
+ final_program = loop_results.get('final_program', "") # Use .get for safety
275
+ final_code = loop_results.get('final_code', "") # Use .get for safety
276
+ attempts = loop_results.get('total_attempts', 0) # Use .get for safety
277
+ total_cost = loop_results.get('total_cost', 0.0) # Use .get for safety
278
+ model_name = loop_results.get('model_name', "N/A") # Use .get for safety
279
+ # Capture full statistics if available
280
+ # statistics = loop_results.get('statistics', {})
281
+ except Exception as e:
282
+ rich_print(f"[bold red]Error during loop execution:[/bold red] {e}")
283
+ if verbose:
284
+ import traceback
285
+ rich_print(Panel(traceback.format_exc(), title="Traceback", border_style="red"))
286
+ success = False
282
287
  else: # Single pass verification
283
288
  if not quiet:
284
289
  rich_print("\n[bold blue]Running Single Pass Verification (fix_verification_errors)...[/bold blue]")
@@ -309,7 +314,8 @@ def fix_verification_main(
309
314
  output=program_output,
310
315
  strength=strength,
311
316
  temperature=temperature,
312
- verbose=verbose
317
+ verbose=verbose,
318
+ time=time # Pass time to single pass function
313
319
  )
314
320
 
315
321
  # Determine success: If no issues were found OR if fixes were applied
pdd/generate_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
5
+ from . import EXTRACTION_STRENGTH, DEFAULT_STRENGTH, DEFAULT_TIME
6
6
  from .load_prompt_template import load_prompt_template
7
7
  from .preprocess import preprocess
8
8
  from .llm_invoke import llm_invoke
@@ -15,9 +15,10 @@ console = Console()
15
15
  def generate_test(
16
16
  prompt: str,
17
17
  code: str,
18
- strength: float,
19
- temperature: float,
20
- language: str,
18
+ strength: float=DEFAULT_STRENGTH,
19
+ temperature: float=0.0,
20
+ time: float = DEFAULT_TIME,
21
+ language: str = "python",
21
22
  verbose: bool = False
22
23
  ) -> Tuple[str, float, str]:
23
24
  """
@@ -29,6 +30,7 @@ def generate_test(
29
30
  strength (float): The strength of the LLM model (0-1).
30
31
  temperature (float): The temperature of the LLM model.
31
32
  language (str): The programming language for the unit test.
33
+ time (float, optional): Time budget for LLM calls. Defaults to DEFAULT_TIME.
32
34
  verbose (bool): Whether to print detailed information.
33
35
 
34
36
  Returns:
@@ -62,6 +64,7 @@ def generate_test(
62
64
  input_json=input_json,
63
65
  strength=strength,
64
66
  temperature=temperature,
67
+ time=time,
65
68
  verbose=verbose
66
69
  )
67
70
 
@@ -79,6 +82,7 @@ def generate_test(
79
82
  prompt_text=last_600_chars,
80
83
  strength=strength,
81
84
  temperature=temperature,
85
+ time=time,
82
86
  verbose=verbose
83
87
  )
84
88
  total_cost += check_cost
@@ -92,6 +96,7 @@ def generate_test(
92
96
  llm_output=result,
93
97
  strength=strength,
94
98
  temperature=temperature,
99
+ time=time,
95
100
  verbose=verbose
96
101
  )
97
102
  total_cost += continue_cost
@@ -104,6 +109,7 @@ def generate_test(
104
109
  language=language,
105
110
  strength=EXTRACTION_STRENGTH,
106
111
  temperature=temperature,
112
+ time=time,
107
113
  verbose=verbose
108
114
  )
109
115
  total_cost += post_cost