Skip to content

Commit ddd6bc8

Browse files
authored
Merge pull request #339 from vicsanity623/pyob-evolution-v4-1781233382
Refactor: Add type hints to CodeParser AST visitor methods
2 parents 8d4e8ab + 23415ba commit ddd6bc8

3 files changed

Lines changed: 12 additions & 9 deletions

File tree

src/pyob/entrance.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -535,11 +535,12 @@ def update_ledger_for_file(self, rel_path: str, code: str):
535535
elif isinstance(n.func, ast.Attribute):
536536
potential_refs.add(n.func.attr)
537537
elif isinstance(n, ast.Name) and isinstance(n.ctx, ast.Load):
538-
potential_refs.add(n.id)
538+
if n.id not in ["self", "None", "True", "False"]:
539+
potential_refs.add(n.id)
539540
except Exception as e:
540541
logger.warning(f"Failed to parse Python AST for {rel_path}: {e}")
541542
potential_refs.update(
542-
re.findall(r"\b[a-zA-Z_][a-zA-Z0-9_]{3,}\b", code)
543+
re.findall(r"\b[a-zA-Z_][a-zA-Z0-9_]{4,}\b", code)
543544
)
544545
elif ext in [".js", ".ts"]:
545546
defs = re.findall(

src/pyob/prompts.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ def validate_prompts(prompts: Dict[str, str]) -> None:
3838
"PP.md": "You are an elite PYOB Software Engineer. Analyze the code for bugs or architectural gaps.\n\n{memory_section}{ruff_section}{mypy_section}{custom_issues_section}### Source Code:\n```{lang_tag}\n{content}\n```\n\n### CRITICAL RULES:\n1. **ITERATION BUDGET**:\n - IF iteration < 5: Focus ONLY on bug fixes. Do NOT refactor.\n2. **SURGICAL FIXES**: Every <SEARCH> block must be exactly 2-5 lines. Only provide ONE <EDIT> block. Do NOT repeat the entire file.\n3. **STRICT TYPING (PYTHON ONLY)**: If the target file is Python, it uses strict mypy. Every new or modified function MUST have complete argument and return type hints (e.g., `def foo(x: int) -> str:`). For HTML/JavaScript/CSS files, do NOT use type annotations or TypeScript syntax.\n4. **EXTERNAL IMPORTS (PYTHON ONLY)**: If the target file is Python and you import a third-party library that gets a `[no-any-unimported]` error, you MUST append `# type: ignore` to that import statement.\n5. **NO HALLUCINATIONS**: If the code is functional, state 'The code looks good.'\n6. **NO CHATTER**: Be brief. Do not explain things unless necessary.\n7. **SYMBOL SAFETY (MANDATORY)**: The following symbols in this file are referenced by OTHER files in this project. You MUST NOT rename them, change their signatures, or remove them: {symbol_safety_list}\n If you believe a rename would help clarity, output a # TODO comment only. Never rename.\n8. **INTERFACE PRESERVATION**: All public function signatures must remain identical. You may change internals freely. You may NOT change parameter names, counts, or return types of any existing public function.\n9. **FRONTEND LAYOUT & CONTROLS SAFETY**: For HTML/CSS/JS files: (a) Ensure CSS selectors match the exact IDs/classes in the HTML. (b) Never set `overflow: hidden;` on elements where inner shadows/glows must be visible. (c) If a wrapper container has `overflow-y: auto` or `scroll`, bind scroll listeners and scroll actions to that container element instead of `window`.\n10. **STRICT INDENTATION (CRITICAL)**: You MUST use perfect 4-space indentation for all Python code. NEVER use raw tab characters. Match the absolute indentation level of the surrounding code block exactly.\n11. **NO SINGLE-LINE COLONS**: Never put statements on the same line as a colon (e.g., do NOT write 'if x: continue' or 'except: pass'). Always put the statement on a new, indented line.\n\n### HOW TO RESPOND:\n<THOUGHT>\nSummary: ...\nAction: ...\n</THOUGHT>\n<EDIT>\n<SEARCH>\n...\n</SEARCH>\n<REPLACE>\n...\n</REPLACE>\n</EDIT>",
3939
"ALF.md": "You are an elite developer fixing syntax errors.\nThe file `{rel_path}` failed validation with these exact errors:\n{err_text}\n\n### Current Code:\n```\n{code}\n```\n\n### Instructions:\n1. Fix the syntax errors (like stray brackets, unexpected tokens, or indentation) using surgical XML edits.\n2. Respond EXCLUSIVELY with a <THOUGHT> block followed by ONE OR MORE <EDIT> blocks.\n3. Ensure your edits use perfect absolute 4-space indentation and perfectly align with the surrounding brackets. NEVER use raw tab characters.",
4040
"FRE.md": "You are an elite PYOB developer fixing runtime crashes.\n{memory_section}The application crashed during a test run.\n\n### Crash Logs & Traceback:\n{logs}\n\nThe traceback indicates the error occurred in `{rel_path}`.\n\n### Current Code of `{rel_path}`:\n```python\n{code}\n```\n\n### Instructions:\n1. Identify the EXACT root cause of the crash.\n2. Fix the error using surgical XML edits.\n3. Respond EXCLUSIVELY with a <THOUGHT> block followed by ONE OR MORE <EDIT> blocks.\n\n### REQUIRED XML FORMAT:\n<THOUGHT>\nExplanation of root cause...\nImports Needed: [List new imports required or 'None']\n</THOUGHT>\n<EDIT>\n<SEARCH>\nExact lines to replace\n</SEARCH>\n<REPLACE>\nNew replacement lines\n</REPLACE>\n</EDIT>",
41-
"PF.md": 'You are the PYOB Product Architect. Review the source code and suggest ONE highly useful, INTERACTIVE feature.\n\n{memory_section}### Source Code ({lang_name}):\n```{lang_tag}\n{content}\n```\n\n### CRITICAL RULES:\n1. Suggest ONE INTERACTIVE feature relevant to the file\'s language ({lang_name}).\n2. **PYTHON ONLY — ARCHITECTURAL SPLIT**: If the language is Python AND the source is over 800 lines, propose splitting a logical module into a new `.py` file instead of a feature. Use <CREATE_FILE path="new_filename.py">[code]</CREATE_FILE> inside <SNIPPET>.\n3. **PYTHON ONLY — STRICT TYPING**: For Python files only, all new code MUST include strict type hints.\n4. **HTML/JS/CSS**: For frontend files, propose UI/UX enhancements — new interactive elements, improved user flow, animations, or data visualisations. Do NOT suggest Python-style type hints or file splits.\n5. MULTI-FILE ORCHESTRATION: In your <THOUGHT>, list any other files that will need updating.\n6. **NO PREAMBLE**: Do NOT explain what you are about to do before outputting XML. Output ONLY the XML blocks.\n\n### REQUIRED XML FORMAT (output this and nothing else):\n<THOUGHT>\n[Your reasoning and list of affected files]\n</THOUGHT>\n<SNIPPET>\n[New code snippet or <CREATE_FILE> block]\n</SNIPPET>',
42-
"IF.md": "You are an elite PYOB Implementation Engineer. Implement the APPROVED feature into `{rel_path}`.\n\n{memory_section}### Feature Proposal Details:\n{feature_content}\n\n### Current Source Code:\n```{lang_tag}\n{source_code}\n```\n\n### CRITICAL INSTRUCTIONS:\n1. **SURGICAL EDITS**: <SEARCH> blocks must be 2-5 lines. NEVER output the entire file.\n2. **STRICT TYPING (PYTHON ONLY)**: If the target file is Python, you MUST add explicit type hints to any new variables or functions you create to satisfy `mypy --strict`. For HTML/JavaScript/CSS files, do NOT use type annotations or TypeScript syntax.\n3. **UNFOLLOWED IMPORTS (PYTHON ONLY)**: If the target file is Python and you add a new import for an external library, append `# type: ignore` to it.\n4. **NO MASS DELETIONS**: Do not replace large blocks with small ones without structure.\n5. **NO CHATTER**: Do not explain your code. Just provide the XML blocks.\n6. **SYMBOL SAFETY (MANDATORY)**: The following symbols in this file are referenced by OTHER files in this project. You MUST NOT rename them, change their signatures, or remove them: {symbol_safety_list}\n If you believe a rename would help clarity, output a # TODO comment only. Never rename.\n7. **INTERFACE PRESERVATION**: All public function signatures must remain identical. You may change internals freely. You may NOT change parameter names, counts, or return types of any existing public function.\n8. **FRONTEND LAYOUT & CONTROLS SAFETY**: For HTML/CSS/JS files: (a) Ensure CSS selectors match the exact IDs/classes in the HTML. (b) Never set `overflow: hidden;` on elements where inner shadows/glows must be visible. (c) If a wrapper container has `overflow-y: auto` or `scroll`, bind scroll listeners and scroll actions to that container element instead of `window`.\n9. **STRICT INDENTATION (CRITICAL)**: You MUST use perfect 4-space indentation for all Python code. NEVER use raw tab characters. Ensure all statements inside your replacement blocks align perfectly with the surrounding code blocks.\n10. **NO SINGLE-LINE COLONS**: Never put statements on the same line as a colon (e.g., do NOT write 'if x: continue' or 'except: pass'). Always put the statement on a new, indented line.\n\n### REQUIRED XML FORMAT:\n<THOUGHT>\n...\n</THOUGHT>\n<EDIT>\n<SEARCH>\n...\n</SEARCH>\n<REPLACE>\n...\n</REPLACE>\n</EDIT>",
41+
"PF.md": 'You are the PYOB Product Architect. Review the source code and suggest ONE highly useful, INTERACTIVE feature.\n\n{memory_section}### Source Code ({lang_name}):\n```{lang_tag}\n{content}\n```\n\n### CRITICAL RULES:\n1. Suggest ONE INTERACTIVE feature relevant to the file\'s language ({lang_name}).\n2. **PYTHON ONLY — ARCHITECTURAL SPLIT**: If the language is Python AND the source is over 800 lines, propose splitting a logical module into a new `.py` file instead of a feature. Use <CREATE_FILE path="new_filename.py">[code]</CREATE_FILE> inside <SNIPPET>.\n3. **PYTHON ONLY — STRICT TYPING**: For Python files only, all new code MUST include strict type hints.\n4. **HTML/JS/CSS**: For frontend files, propose UI/UX enhancements — new interactive elements, improved user flow, animations, or data visualisations. Do NOT suggest Python-style type hints or file splits.\n5. MULTI-FILE ORCHESTRATION: In your <THOUGHT>, list any other files that will need updating.\n6. **NO PREAMBLE**: Do NOT explain what you are about to do before outputting XML. Output ONLY the XML blocks.\n7. **MIGRATION SIGNATURE INTEGRITY**: When proposing an Architectural Split that moves functions (including private/underscore methods) to a new module, you MUST preserve their exact parameter counts, names, and type annotations so that dependent calls in the original file do not break.\n\n### REQUIRED XML FORMAT (output this and nothing else):\n<THOUGHT>\n[Your reasoning and list of affected files]\n</THOUGHT>\n<SNIPPET>\n[New code snippet or <CREATE_FILE> block]\n</SNIPPET>',
42+
"IF.md": "You are an elite PYOB Implementation Engineer. Implement the APPROVED feature into `{rel_path}`.\n\n{memory_section}### Feature Proposal Details:\n{feature_content}\n\n### Current Source Code:\n```{lang_tag}\n{source_code}\n```\n\n### CRITICAL INSTRUCTIONS:\n1. **SURGICAL EDITS**: <SEARCH> blocks must be 2-5 lines. NEVER output the entire file.\n2. **STRICT TYPING (PYTHON ONLY)**: If the target file is Python, you MUST add explicit type hints to any new variables or functions you create to satisfy `mypy --strict`. For HTML/JavaScript/CSS files, do NOT use type annotations or TypeScript syntax.\n3. **UNFOLLOWED IMPORTS (PYTHON ONLY)**: If the target file is Python and you add a new import for an external library, append `# type: ignore` to it.\n4. **NO MASS DELETIONS**: Do not replace large blocks with small ones without structure.\n5. **NO CHATTER**: Do not explain your code. Just provide the XML blocks.\n6. **SYMBOL SAFETY (MANDATORY)**: The following symbols in this file are referenced by OTHER files in this project. You MUST NOT rename them, change their signatures, or remove them: {symbol_safety_list}\n If you believe a rename would help clarity, output a # TODO comment only. Never rename.\n7. **INTERFACE PRESERVATION**: All public function signatures must remain identical. You may change internals freely. You may NOT change parameter names, counts, or return types of any existing public function.\n8. **FRONTEND LAYOUT & CONTROLS SAFETY**: For HTML/CSS/JS files: (a) Ensure CSS selectors match the exact IDs/classes in the HTML. (b) Never set `overflow: hidden;` on elements where inner shadows/glows must be visible. (c) If a wrapper container has `overflow-y: auto` or `scroll`, bind scroll listeners and scroll actions to that container element instead of `window`.\n9. **STRICT INDENTATION (CRITICAL)**: You MUST use perfect 4-space indentation for all Python code. NEVER use raw tab characters. Ensure all statements inside your replacement blocks align perfectly with the surrounding code blocks.\n10. **NO SINGLE-LINE COLONS**: Never put statements on the same line as a colon (e.g., do NOT write 'if x: continue' or 'except: pass'). Always put the statement on a new, indented line.\n11. **MIGRATION SIGNATURE INTEGRITY**: When implementing an Architectural Split, you MUST preserve the exact parameter counts, names, and type annotations of all migrated functions (including private/underscore methods) so that dependent calls in the original file do not break.\n\n### REQUIRED XML FORMAT:\n<THOUGHT>\n...\n</THOUGHT>\n<EDIT>\n<SEARCH>\n...\n</SEARCH>\n<REPLACE>\n...\n</REPLACE>\n</EDIT>",
4343
"PCF.md": 'You are the PYOB Symbolic Fixer taking over Phase 3 Cascaded Edits.\n{memory_section}We just modified `{trigger_file}`, and it broke a dependency downstream: `{rel_broken_path}`.\n\n### Linter Errors for `{rel_broken_path}`:\n{mypy_errors}\n\n### Source Code of `{rel_broken_path}`:\n```python\n{broken_code}\n```\n\n### Instructions:\n1. Respond EXCLUSIVELY with a <THOUGHT> block followed by ONE <EDIT> block to fix the broken references.\n2. **DEFEATING MYPY (PYTHON ONLY)**: If the file is Python and the error contains `[union-attr]` or states `Item "None" of ... has no attribute`, adding a type hint will fail. You MUST fix this by either inserting `assert variable is not None` before the operation, or adding `# type: ignore` to the end of the failing line.\n3. **UNIMPORTED ERRORS (PYTHON ONLY)**: If the file is Python and the error is `[no-any-unimported]`, you MUST append `# type: ignore` to the import statement causing it.\n4. **STRICT INDENTATION**: You MUST use perfect 4-space indentation for all Python code. NEVER use raw tab characters. Match the exact indentation level of the surrounding code.\n\n### REQUIRED XML FORMAT:\n<THOUGHT>\nExplanation of cascade fix...\n</THOUGHT>\n<EDIT>\n<SEARCH>\nExact lines to replace\n</SEARCH>\n<REPLACE>\nNew replacement lines\n</REPLACE>\n</EDIT>',
4444
"PIR.md": "You are an elite PYOB developer performing a post-implementation repair.\nAn automated attempt to implement a feature or bugfix has failed, resulting in the following errors.\n\n### Original Goal / Change Request:\n{context_of_change}\n\n### The Resulting Errors (Linter/Runtime):\n{err_text}\n\n### The Broken Code in `{rel_path}`:\n```\n{code}\n```\n\n### Instructions:\n1. Analyze the 'Original Goal' and the 'Resulting Errors' together.\n2. CRITICAL IMPORT CHECK (PYTHON ONLY): If the file is Python and the error is `F821 Undefined name`, you MUST create an <EDIT> block at the top of the file to add the missing `import` statement.\n3. **DEFEATING MYPY [no-any-unimported] (PYTHON ONLY)**: If the file is Python and the error says `due to an unfollowed import [no-any-unimported]`, you MUST locate the import statement for that library and append `# type: ignore` to the end of that line.\n4. **DEFEATING MYPY [union-attr] (PYTHON ONLY)**: If the file is Python and the error is a `[union-attr]` or `None` type error, insert `assert object is not None` right before it is used, or append `# type: ignore` to the failing line.\n5. **CRITICAL INDENTATION CHECK**: If the error mentions indentation or unindent, you MUST rewrite the <EDIT> block using perfect absolute 4-space indentation. NEVER use raw tab characters. Ensure every line aligns perfectly with the adjacent untouched code lines.\n6. Create a surgical XML edit to fix the code.\n\n### REQUIRED XML FORMAT:\n<THOUGHT>\nRoot Cause: ...\nImports Needed: ...\nAction: ...\n</THOUGHT>\n<EDIT>\n<SEARCH>\nExact lines to replace\n</SEARCH>\n<REPLACE>\nNew replacement lines\n</REPLACE>\n</EDIT>",
4545
}

src/pyob/pyob_code_parser.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,27 +37,29 @@ def visit_Import(self, node: ast.Import) -> None:
3737
except Exception:
3838
pass
3939

40-
def visit_ImportFrom(self, node):
40+
def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
4141
try:
4242
self.imports.append(ast.unparse(node))
4343
except Exception:
4444
pass
4545

46-
def visit_ClassDef(self, node):
46+
def visit_ClassDef(self, node: ast.ClassDef) -> None:
4747
self.classes.append(f"class {node.name}")
4848
old_class = self.current_class
4949
self.current_class = node.name
5050
for child in node.body:
5151
self.visit(child)
5252
self.current_class = old_class
5353

54-
def visit_FunctionDef(self, node):
54+
def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
5555
self.handle_function(node)
5656

57-
def visit_AsyncFunctionDef(self, node):
57+
def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None:
5858
self.handle_function(node)
5959

60-
def handle_function(self, node):
60+
def handle_function(
61+
self, node: ast.FunctionDef | ast.AsyncFunctionDef
62+
) -> None:
6163
args = []
6264
for arg in node.args.args:
6365
if self.current_class and arg.arg == "self":

0 commit comments

Comments
 (0)