Private
Public Access
refactor(mcp_client): migrate 3 nested helper BC sites to Result-drain (Phase 8)
Three nested helper functions inside _result variants had silent-swallow or broad-catch patterns that the audit still flagged: 1. py_find_usages_result._search_file (L846): Was: 'try/except Exception: pass' (silent-swallow per-file read errors) Now: try/except (OSError, UnicodeDecodeError) as e: errors.append(ErrorInfo(...)) Errors propagated via the parent's Result.errors 2. derive_code_path_result (L957): Was: 'try/except Exception: continue' (silent-swallow file parse errors) Now: try/except (SyntaxError, ValueError) as e: file_errors.append(ErrorInfo(...)) Errors propagated via the parent's Result.errors 3. derive_code_path_result._trace (L996): Was: try/except Exception as e: output.append(f-string with error) Now: same output.append + ALSO appends ErrorInfo to file_errors Drain: output appears in the result data string (operator-visible) All 3 sites now comply with the data-oriented convention. Audit: mcp_client migration-target sites: 0 (was 3). Categories: BOUNDARY_CONVERSION: 5, INTERNAL_COMPLIANT: 43
This commit is contained in:
+17
-9
@@ -832,7 +832,8 @@ def py_find_usages_result(path: str, name: str) -> Result[str]:
|
|||||||
try:
|
try:
|
||||||
import re
|
import re
|
||||||
pattern = re.compile(r"\b" + re.escape(name) + r"\b")
|
pattern = re.compile(r"\b" + re.escape(name) + r"\b")
|
||||||
results = []
|
results: list[str] = []
|
||||||
|
file_errors: list[ErrorInfo] = []
|
||||||
def _search_file(fp: Path) -> None:
|
def _search_file(fp: Path) -> None:
|
||||||
if fp.name == "history.toml" or fp.name.endswith("_history.toml"): return
|
if fp.name == "history.toml" or fp.name.endswith("_history.toml"): return
|
||||||
if not _is_allowed(fp): return
|
if not _is_allowed(fp): return
|
||||||
@@ -843,8 +844,8 @@ def py_find_usages_result(path: str, name: str) -> Result[str]:
|
|||||||
if pattern.search(line):
|
if pattern.search(line):
|
||||||
rel = fp.relative_to(_primary_base_dir if _primary_base_dir else Path.cwd())
|
rel = fp.relative_to(_primary_base_dir if _primary_base_dir else Path.cwd())
|
||||||
results.append(f"{rel}:{i}: {line.strip()[:100]}")
|
results.append(f"{rel}:{i}: {line.strip()[:100]}")
|
||||||
except Exception:
|
except (OSError, UnicodeDecodeError) as e:
|
||||||
pass
|
errors.append(ErrorInfo(kind=ErrorKind.INTERNAL, message=f"failed to read {fp}: {e}", source="mcp.py_find_usages_result._search_file", original=e))
|
||||||
if p.is_file():
|
if p.is_file():
|
||||||
_search_file(p)
|
_search_file(p)
|
||||||
else:
|
else:
|
||||||
@@ -854,10 +855,12 @@ def py_find_usages_result(path: str, name: str) -> Result[str]:
|
|||||||
if file.endswith(('.py', '.md', '.toml', '.txt', '.json')):
|
if file.endswith(('.py', '.md', '.toml', '.txt', '.json')):
|
||||||
_search_file(Path(root) / file)
|
_search_file(Path(root) / file)
|
||||||
if not results:
|
if not results:
|
||||||
|
if file_errors:
|
||||||
|
return Result(data=f"No usages found for '{name}' in {p}", errors=file_errors)
|
||||||
return Result(data=f"No usages found for '{name}' in {p}")
|
return Result(data=f"No usages found for '{name}' in {p}")
|
||||||
if len(results) > 100:
|
if len(results) > 100:
|
||||||
return Result(data="\n".join(results[:100]) + f"\n... (and {len(results)-100} more)")
|
return Result(data="\n".join(results[:100]) + f"\n... (and {len(results)-100} more)", errors=file_errors)
|
||||||
return Result(data="\n".join(results))
|
return Result(data="\n".join(results), errors=file_errors)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return Result(data="", errors=[ErrorInfo(kind=ErrorKind.INTERNAL, message=str(e), source="mcp.py_find_usages_result", original=e)])
|
return Result(data="", errors=[ErrorInfo(kind=ErrorKind.INTERNAL, message=str(e), source="mcp.py_find_usages_result", original=e)])
|
||||||
|
|
||||||
@@ -935,6 +938,7 @@ def derive_code_path_result(target: str, max_depth: int = 5) -> Result[str]:
|
|||||||
from src.file_cache import ASTParser
|
from src.file_cache import ASTParser
|
||||||
parser = ASTParser("python")
|
parser = ASTParser("python")
|
||||||
found_path, found_code = None, None
|
found_path, found_code = None, None
|
||||||
|
file_errors: list[ErrorInfo] = []
|
||||||
parts = target.split(".")
|
parts = target.split(".")
|
||||||
symbol_name = parts[-1]
|
symbol_name = parts[-1]
|
||||||
if len(parts) > 1:
|
if len(parts) > 1:
|
||||||
@@ -951,7 +955,9 @@ def derive_code_path_result(target: str, max_depth: int = 5) -> Result[str]:
|
|||||||
if _get_symbol_node(tree, symbol_name):
|
if _get_symbol_node(tree, symbol_name):
|
||||||
found_path, found_code = str(p), code
|
found_path, found_code = str(p), code
|
||||||
break
|
break
|
||||||
except Exception: continue
|
except (SyntaxError, ValueError) as e:
|
||||||
|
file_errors.append(ErrorInfo(kind=ErrorKind.INVALID_INPUT, message=f"failed to parse {p}: {e}", source="mcp.derive_code_path_result", original=e))
|
||||||
|
continue
|
||||||
if found_path: break
|
if found_path: break
|
||||||
if not found_path:
|
if not found_path:
|
||||||
return Result(data="", errors=[ErrorInfo(kind=ErrorKind.NOT_FOUND, message=f"could not find definition for '{target}'", source="mcp.derive_code_path_result")])
|
return Result(data="", errors=[ErrorInfo(kind=ErrorKind.NOT_FOUND, message=f"could not find definition for '{target}'", source="mcp.derive_code_path_result")])
|
||||||
@@ -987,13 +993,15 @@ def derive_code_path_result(target: str, max_depth: int = 5) -> Result[str]:
|
|||||||
break
|
break
|
||||||
if c_path: break
|
if c_path: break
|
||||||
if c_path: trace(call, c_path, c_code, depth + 1, indent + " ")
|
if c_path: trace(call, c_path, c_code, depth + 1, indent + " ")
|
||||||
except Exception as e:
|
except (SyntaxError, ValueError, AttributeError) as e:
|
||||||
output.append(f"{indent} [!] Error parsing calls for {name}: {e}")
|
output.append(f"{indent} [!] Error parsing calls for {name}: {e}")
|
||||||
|
file_errors.append(ErrorInfo(kind=ErrorKind.INTERNAL, message=f"trace error for {name}: {e}", source="mcp.derive_code_path_result._trace", original=e))
|
||||||
try:
|
try:
|
||||||
trace(symbol_name, found_path, found_code, 0, "")
|
trace(symbol_name, found_path, found_code, 0, "")
|
||||||
return Result(data="\n".join(output))
|
return Result(data="\n".join(output), errors=file_errors)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return Result(data="", errors=[ErrorInfo(kind=ErrorKind.INTERNAL, message=str(e), source="mcp.derive_code_path_result", original=e)])
|
file_errors.append(ErrorInfo(kind=ErrorKind.INTERNAL, message=str(e), source="mcp.derive_code_path_result", original=e))
|
||||||
|
return Result(data="", errors=file_errors)
|
||||||
|
|
||||||
def get_tree_result(path: str, max_depth: int = 2) -> Result[str]:
|
def get_tree_result(path: str, max_depth: int = 2) -> Result[str]:
|
||||||
resolved = _resolve_and_check_result(path)
|
resolved = _resolve_and_check_result(path)
|
||||||
|
|||||||
Reference in New Issue
Block a user