pdd-cli 0.0.24__py3-none-any.whl → 0.0.25__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 (43) hide show
  1. pdd/__init__.py +7 -1
  2. pdd/bug_main.py +5 -1
  3. pdd/bug_to_unit_test.py +16 -5
  4. pdd/change.py +2 -1
  5. pdd/change_main.py +407 -189
  6. pdd/cli.py +853 -301
  7. pdd/code_generator.py +2 -1
  8. pdd/conflicts_in_prompts.py +2 -1
  9. pdd/construct_paths.py +377 -222
  10. pdd/context_generator.py +2 -1
  11. pdd/continue_generation.py +3 -2
  12. pdd/crash_main.py +55 -20
  13. pdd/detect_change.py +2 -1
  14. pdd/fix_code_loop.py +465 -160
  15. pdd/fix_code_module_errors.py +7 -4
  16. pdd/fix_error_loop.py +9 -9
  17. pdd/fix_errors_from_unit_tests.py +207 -365
  18. pdd/fix_main.py +31 -4
  19. pdd/fix_verification_errors.py +60 -34
  20. pdd/fix_verification_errors_loop.py +842 -768
  21. pdd/fix_verification_main.py +412 -0
  22. pdd/generate_output_paths.py +427 -189
  23. pdd/generate_test.py +3 -2
  24. pdd/increase_tests.py +2 -2
  25. pdd/llm_invoke.py +14 -3
  26. pdd/preprocess.py +3 -3
  27. pdd/process_csv_change.py +466 -154
  28. pdd/prompts/extract_prompt_update_LLM.prompt +11 -5
  29. pdd/prompts/extract_unit_code_fix_LLM.prompt +2 -2
  30. pdd/prompts/fix_code_module_errors_LLM.prompt +29 -0
  31. pdd/prompts/fix_errors_from_unit_tests_LLM.prompt +5 -5
  32. pdd/prompts/generate_test_LLM.prompt +9 -3
  33. pdd/prompts/update_prompt_LLM.prompt +3 -3
  34. pdd/split.py +6 -5
  35. pdd/split_main.py +13 -4
  36. pdd/trace_main.py +7 -0
  37. pdd/xml_tagger.py +2 -1
  38. {pdd_cli-0.0.24.dist-info → pdd_cli-0.0.25.dist-info}/METADATA +4 -4
  39. {pdd_cli-0.0.24.dist-info → pdd_cli-0.0.25.dist-info}/RECORD +43 -42
  40. {pdd_cli-0.0.24.dist-info → pdd_cli-0.0.25.dist-info}/WHEEL +1 -1
  41. {pdd_cli-0.0.24.dist-info → pdd_cli-0.0.25.dist-info}/entry_points.txt +0 -0
  42. {pdd_cli-0.0.24.dist-info → pdd_cli-0.0.25.dist-info}/licenses/LICENSE +0 -0
  43. {pdd_cli-0.0.24.dist-info → pdd_cli-0.0.25.dist-info}/top_level.txt +0 -0
pdd/context_generator.py CHANGED
@@ -5,6 +5,7 @@ from .llm_invoke import llm_invoke
5
5
  from .unfinished_prompt import unfinished_prompt
6
6
  from .continue_generation import continue_generation
7
7
  from .postprocess import postprocess
8
+ from . import EXTRACTION_STRENGTH
8
9
 
9
10
  def context_generator(code_module: str, prompt: str, language: str = "python", strength: float = 0.5, temperature: float = 0, verbose: bool = False) -> tuple:
10
11
  """
@@ -115,7 +116,7 @@ def context_generator(code_module: str, prompt: str, language: str = "python", s
115
116
  example_code, postprocess_cost, postprocess_model = postprocess(
116
117
  llm_output=final_llm_output,
117
118
  language=language,
118
- strength=0.97,
119
+ strength=EXTRACTION_STRENGTH,
119
120
  temperature=temperature,
120
121
  verbose=verbose
121
122
  )
@@ -6,6 +6,7 @@ from .load_prompt_template import load_prompt_template
6
6
  from .preprocess import preprocess
7
7
  from .llm_invoke import llm_invoke
8
8
  from .unfinished_prompt import unfinished_prompt
9
+ from . import EXTRACTION_STRENGTH
9
10
 
10
11
  console = Console()
11
12
 
@@ -69,7 +70,7 @@ def continue_generation(
69
70
  trim_start_response = llm_invoke(
70
71
  prompt=processed_prompts['trim_start'],
71
72
  input_json={"LLM_OUTPUT": llm_output},
72
- strength=0.9,
73
+ strength=0.8,
73
74
  temperature=0,
74
75
  output_pydantic=TrimResultsStartOutput,
75
76
  verbose=verbose
@@ -119,7 +120,7 @@ def continue_generation(
119
120
  "CONTINUED_GENERATION": continue_result,
120
121
  "GENERATED_RESULTS": code_block[-200:]
121
122
  },
122
- strength=0.9,
123
+ strength=EXTRACTION_STRENGTH,
123
124
  temperature=0,
124
125
  output_pydantic=TrimResultsOutput,
125
126
  verbose=verbose
pdd/crash_main.py CHANGED
@@ -1,10 +1,18 @@
1
1
  import sys
2
- from typing import Tuple, Optional
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
6
+ from pathlib import Path
5
7
 
6
8
  from .construct_paths import construct_paths
7
9
  from .fix_code_loop import fix_code_loop
10
+ # Import fix_code_module_errors conditionally or ensure it's always available
11
+ try:
12
+ from .fix_code_module_errors import fix_code_module_errors
13
+ except ImportError:
14
+ # Handle case where fix_code_module_errors might not be available if not needed
15
+ fix_code_module_errors = None
8
16
 
9
17
  def crash_main(
10
18
  ctx: click.Context,
@@ -39,6 +47,13 @@ def crash_main(
39
47
  - float: Total cost of all fix attempts
40
48
  - str: The name of the model used
41
49
  """
50
+ # Ensure ctx.obj and ctx.params exist and are dictionaries
51
+ ctx.obj = ctx.obj if isinstance(ctx.obj, dict) else {}
52
+ ctx.params = ctx.params if isinstance(ctx.params, dict) else {}
53
+
54
+ quiet = ctx.params.get("quiet", ctx.obj.get("quiet", False))
55
+ verbose = ctx.params.get("verbose", ctx.obj.get("verbose", False)) # Get verbose flag
56
+
42
57
  try:
43
58
  # Construct file paths
44
59
  input_file_paths = {
@@ -47,13 +62,13 @@ def crash_main(
47
62
  "program_file": program_file,
48
63
  "error_file": error_file
49
64
  }
50
- command_options = {
65
+ command_options: Dict[str, Any] = {
51
66
  "output": output,
52
67
  "output_program": output_program
53
68
  }
54
69
 
55
70
  force = ctx.params.get("force", ctx.obj.get("force", False))
56
- quiet = ctx.params.get("quiet", ctx.obj.get("quiet", False))
71
+ # quiet = ctx.params.get("quiet", ctx.obj.get("quiet", False)) # Already defined above
57
72
 
58
73
  input_strings, output_file_paths, _ = construct_paths(
59
74
  input_file_paths=input_file_paths,
@@ -70,46 +85,58 @@ def crash_main(
70
85
  error_content = input_strings["error_file"]
71
86
 
72
87
  # Get model parameters from context
73
- strength = ctx.obj.get("strength", 0.97)
88
+ strength = ctx.obj.get("strength", DEFAULT_STRENGTH)
74
89
  temperature = ctx.obj.get("temperature", 0)
75
90
 
76
- verbose = ctx.params.get("verbose", ctx.obj.get("verbose", False))
91
+ # verbose = ctx.params.get("verbose", ctx.obj.get("verbose", False)) # Already defined above
77
92
 
78
93
  if loop:
79
94
  # Use iterative fixing process
80
- success, final_code, final_program, attempts, cost, model = fix_code_loop(
95
+ success, final_program, final_code, attempts, cost, model = fix_code_loop(
81
96
  code_file, prompt_content, program_file, strength, temperature, max_attempts or 3, budget or 5.0, error_file, verbose
82
97
  )
83
98
  else:
84
99
  # Use single fix attempt
85
- from .fix_code_module_errors import fix_code_module_errors
86
- update_program, update_code, final_program, final_code, cost, model = fix_code_module_errors(
100
+ if fix_code_module_errors is None:
101
+ 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(
87
106
  program_content, prompt_content, code_content, error_content, strength, temperature, verbose
88
107
  )
89
- success = True
108
+ success = True # Assume success after one attempt if no exception
90
109
  attempts = 1
91
110
 
92
111
  # Ensure we have content to write, falling back to original content if needed
93
- if final_code == "":
94
- final_code = code_content
95
-
96
112
  if final_program == "":
97
113
  final_program = program_content
98
114
 
115
+ if final_code == "":
116
+ final_code = code_content
117
+
99
118
  # Determine whether to write the files based on whether paths are provided
100
- should_write_code = output_file_paths.get("output") is not None
101
- should_write_program = output_file_paths.get("output_program") is not None
119
+ output_code_path_str = output_file_paths.get("output")
120
+ output_program_path_str = output_file_paths.get("output_program")
121
+
122
+ should_write_code = output_code_path_str is not None
123
+ should_write_program = output_program_path_str is not None
102
124
 
103
125
  # Write output files
104
126
  if should_write_code:
105
- with open(output_file_paths["output"], "w") as f:
127
+ output_code_path = Path(output_code_path_str)
128
+ output_code_path.parent.mkdir(parents=True, exist_ok=True) # Ensure directory exists
129
+ with open(output_code_path, "w") as f:
106
130
  f.write(final_code)
107
131
 
108
132
  if should_write_program:
109
- with open(output_file_paths["output_program"], "w") as f:
133
+ output_program_path = Path(output_program_path_str)
134
+ output_program_path.parent.mkdir(parents=True, exist_ok=True) # Ensure directory exists
135
+ with open(output_program_path, "w") as f:
110
136
  f.write(final_program)
111
137
 
112
- # Provide user feedback
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:'
113
140
  if not quiet:
114
141
  if success:
115
142
  rprint("[bold green]Crash fix completed successfully.[/bold green]")
@@ -119,13 +146,21 @@ def crash_main(
119
146
  rprint(f"[bold]Total attempts:[/bold] {attempts}")
120
147
  rprint(f"[bold]Total cost:[/bold] ${cost:.2f}")
121
148
  if should_write_code:
122
- rprint(f"[bold]Fixed code saved to:[/bold] {output_file_paths['output']}")
149
+ rprint(f"[bold]Fixed code saved to:[/bold] {output_code_path_str}")
123
150
  if should_write_program:
124
- rprint(f"[bold]Fixed program saved to:[/bold] {output_file_paths['output_program']}")
151
+ rprint(f"[bold]Fixed program saved to:[/bold] {output_program_path_str}")
125
152
 
126
153
  return success, final_code, final_program, attempts, cost, model
127
154
 
155
+ except FileNotFoundError as e:
156
+ if not quiet:
157
+ # Provide a more specific error message for file not found
158
+ rprint(f"[bold red]Error:[/bold red] Input file not found: {e}")
159
+ sys.exit(1)
128
160
  except Exception as e:
129
161
  if not quiet:
130
- rprint(f"[bold red]Error:[/bold red] {str(e)}")
162
+ rprint(f"[bold red]An unexpected error occurred:[/bold red] {str(e)}")
163
+ # Consider logging the full traceback here for debugging
164
+ # import traceback
165
+ # traceback.print_exc()
131
166
  sys.exit(1)
pdd/detect_change.py CHANGED
@@ -3,6 +3,7 @@ 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
7
 
7
8
  from .preprocess import preprocess
8
9
  from .load_prompt_template import load_prompt_template
@@ -101,7 +102,7 @@ def detect_change(
101
102
  extract_response = llm_invoke(
102
103
  prompt=extract_prompt,
103
104
  input_json={"llm_output": detect_response['result']},
104
- strength=0.97,
105
+ strength=EXTRACTION_STRENGTH,
105
106
  temperature=0.0,
106
107
  verbose=verbose,
107
108
  output_pydantic=ChangesList