Skip to content

Commit 09602e1

Browse files
haasonsaasclaude
andcommitted
Fix CI lint failures from Lean formalization PR
Addresses ruff violations introduced in #1: trailing/blank-line whitespace (W291/W293), unused variables (F841), open() vs Path.open() (PTH123), nested with statements (SIM117), and missing test docstrings (D102). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2831b51 commit 09602e1

4 files changed

Lines changed: 60 additions & 54 deletions

File tree

formal_verification/hybrid_lean_coq_resolver.py

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@
44
for maximum theorem proving coverage when resolving cognitive dissonance.
55
"""
66

7+
import logging
78
import time
8-
from typing import Any, Optional, Dict, List, Tuple
99
from dataclasses import dataclass
1010
from enum import Enum
11-
import logging
11+
from typing import Any
1212

13-
from .lean_translator import LeanTranslator, LeanStatement
14-
from .lean_prover import LeanProver, ProofResult as LeanProofResult
15-
from .translator import ClaimTranslator
13+
from .lean_prover import LeanProver
14+
from .lean_prover import ProofResult as LeanProofResult
15+
from .lean_translator import LeanTranslator
1616
from .prover import CoqProver
17+
from .translator import ClaimTranslator
1718
from .types import Claim, PropertyType
1819

1920
logger = logging.getLogger(__name__)
@@ -31,8 +32,8 @@ class HybridProofResult:
3132
"""Result from hybrid Lean/Coq prover."""
3233
proven: bool
3334
prover_used: ProverBackend
34-
primary_result: Optional[object] = None
35-
fallback_result: Optional[object] = None
35+
primary_result: object | None = None
36+
fallback_result: object | None = None
3637
combined_confidence: float = 0.0
3738

3839

@@ -48,13 +49,13 @@ def __init__(self, prefer_lean: bool = True, use_fallback: bool = True):
4849
self.coq_prover = CoqProver()
4950

5051
def resolve_conflict(
51-
self, claims: List[Tuple[str, str, str]]
52+
self, claims: list[tuple[str, str, str]]
5253
) -> HybridProofResult:
5354
"""Resolve a conflict between claims using hybrid approach.
54-
55+
5556
Args:
5657
claims: List of (agent_id, claim_text, claim_type) tuples
57-
58+
5859
Returns:
5960
HybridProofResult with proof status and prover backend used
6061
"""
@@ -68,7 +69,7 @@ def resolve_conflict(
6869
primary_result=lean_result,
6970
combined_confidence=0.95,
7071
)
71-
72+
7273
# Fallback to Coq
7374
if self.use_fallback:
7475
coq_result = self._try_coq_proof(claims)
@@ -89,7 +90,7 @@ def resolve_conflict(
8990
primary_result=coq_result,
9091
combined_confidence=0.90,
9192
)
92-
93+
9394
# Fallback to Lean
9495
if self.use_fallback:
9596
lean_result = self._try_lean_proof(claims)
@@ -100,23 +101,23 @@ def resolve_conflict(
100101
fallback_result=lean_result,
101102
combined_confidence=0.85,
102103
)
103-
104+
104105
return HybridProofResult(proven=False, prover_used=ProverBackend.HYBRID)
105106

106-
def _try_lean_proof(self, claims: List[Tuple[str, str, str]]) -> LeanProofResult:
107+
def _try_lean_proof(self, claims: list[tuple[str, str, str]]) -> LeanProofResult:
107108
"""Attempt proof using Lean/LeanDojo."""
108109
try:
109110
# Translate first claim to Lean
110111
claim_text = claims[0][1]
111112
claim_type = claims[0][2]
112-
113+
113114
lean_stmt = self.lean_translator.translate_claim(claim_text, claim_type)
114115
lean_code = self.lean_translator.to_lean_code(lean_stmt)
115-
116+
116117
# Attempt proof
117118
proof_result = self.lean_prover.prove(lean_code, lean_stmt.name)
118119
logger.info(f"Lean proof attempt: {proof_result}")
119-
120+
120121
return proof_result
121122
except Exception as e:
122123
logger.error(f"Lean proof failed: {e}")
@@ -127,7 +128,7 @@ def _try_lean_proof(self, claims: List[Tuple[str, str, str]]) -> LeanProofResult
127128
error_message=str(e),
128129
)
129130

130-
def _try_coq_proof(self, claims: List[Tuple[str, str, str]]) -> Dict[str, Any]:
131+
def _try_coq_proof(self, claims: list[tuple[str, str, str]]) -> dict[str, Any]:
131132
"""Attempt proof using Coq (existing implementation)."""
132133
try:
133134
agent_id, claim_text, claim_type = claims[0]

formal_verification/lean_prover.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
and verification of cognitive dissonance resolutions.
55
"""
66

7-
import subprocess
87
import json
8+
import logging
99
import os
10-
from typing import Optional, Dict, Any, List
10+
import subprocess
1111
from dataclasses import dataclass
12-
import logging
12+
from pathlib import Path
1313

1414
logger = logging.getLogger(__name__)
1515

@@ -19,26 +19,26 @@ class ProofResult:
1919
"""Result of a proof attempt."""
2020
statement_name: str
2121
proven: bool
22-
proof_term: Optional[str] = None
23-
error_message: Optional[str] = None
22+
proof_term: str | None = None
23+
error_message: str | None = None
2424
proof_time_ms: float = 0.0
2525

2626

2727
class LeanProver:
2828
"""Proves Lean 4 theorems using LeanDojo."""
2929

30-
def __init__(self, leandojo_path: Optional[str] = None, timeout_ms: int = 30000):
30+
def __init__(self, leandojo_path: str | None = None, timeout_ms: int = 30000):
3131
self.leandojo_path = leandojo_path or "leandojo"
3232
self.timeout_ms = timeout_ms
33-
self.proof_cache: Dict[str, ProofResult] = {}
33+
self.proof_cache: dict[str, ProofResult] = {}
3434

3535
def prove(self, lean_code: str, statement_name: str) -> ProofResult:
3636
"""Prove a Lean theorem.
37-
37+
3838
Args:
3939
lean_code: Complete Lean 4 code including theorem
4040
statement_name: Name of the theorem to prove
41-
41+
4242
Returns:
4343
ProofResult with proof status and details
4444
"""
@@ -55,7 +55,7 @@ def _attempt_proof(self, lean_code: str, statement_name: str) -> ProofResult:
5555
try:
5656
# Write code to temporary file
5757
temp_file = f"/tmp/lean_{statement_name}.lean"
58-
with open(temp_file, "w") as f:
58+
with Path(temp_file).open("w") as f:
5959
f.write(lean_code)
6060

6161
# Call LeanDojo
@@ -109,13 +109,13 @@ def _attempt_proof(self, lean_code: str, statement_name: str) -> ProofResult:
109109
os.remove(temp_file)
110110

111111
def batch_prove(
112-
self, theorems: List[tuple[str, str]]
113-
) -> List[ProofResult]:
112+
self, theorems: list[tuple[str, str]]
113+
) -> list[ProofResult]:
114114
"""Prove multiple theorems.
115-
115+
116116
Args:
117117
theorems: List of (lean_code, statement_name) tuples
118-
118+
119119
Returns:
120120
List of ProofResults
121121
"""
@@ -125,7 +125,7 @@ def verify_proof(self, lean_code: str) -> bool:
125125
"""Verify that Lean code type-checks."""
126126
try:
127127
temp_file = "/tmp/lean_verify.lean"
128-
with open(temp_file, "w") as f:
128+
with Path(temp_file).open("w") as f:
129129
f.write(lean_code)
130130

131131
result = subprocess.run(

formal_verification/lean_translator.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
"""Lean Formalization Translator via LeanDojo.
22
3-
Translates natural language claims to Lean 4 proofs leveraging the
3+
Translates natural language claims to Lean 4 proofs leveraging the
44
LeanDojo framework for advanced theorem proving capabilities.
55
"""
66

7+
import logging
78
import re
8-
import json
9-
from typing import Optional, Dict, Any
109
from dataclasses import dataclass
11-
import subprocess
12-
import logging
10+
from typing import Any
1311

1412
logger = logging.getLogger(__name__)
1513

@@ -19,24 +17,24 @@ class LeanStatement:
1917
"""Lean theorem/lemma statement."""
2018
name: str
2119
statement: str
22-
proof: Optional[str] = None
23-
namespace: Optional[str] = "CognitiveDissonance"
20+
proof: str | None = None
21+
namespace: str | None = "CognitiveDissonance"
2422

2523

2624
class LeanTranslator:
2725
"""Translates natural language claims to Lean 4 formalization."""
2826

2927
def __init__(self, use_leandojo: bool = True):
3028
self.use_leandojo = use_leandojo
31-
self.translation_cache: Dict[str, LeanStatement] = {}
29+
self.translation_cache: dict[str, LeanStatement] = {}
3230

3331
def translate_claim(self, claim: str, claim_type: str = "arithmetic") -> LeanStatement:
3432
"""Translate a natural language claim to Lean.
35-
33+
3634
Args:
3735
claim: Natural language statement
3836
claim_type: Category of claim (arithmetic, algorithm, invariant, etc.)
39-
37+
4038
Returns:
4139
LeanStatement with Lean 4 formalization
4240
"""
@@ -69,8 +67,6 @@ def _translate_arithmetic(self, claim: str) -> LeanStatement:
6967

7068
if match:
7169
a, op, b, result = match.groups()
72-
op_map = {"+": "HAdd.hAdd", "-": "HSub.hSub", "*": "HMul.hMul", "/": "HDiv.hDiv"}
73-
lean_op = op_map.get(op, "HAdd.hAdd")
7470

7571
statement = f"({a} {op} {b} : Nat) = {result}"
7672
proof = "by omega"
@@ -129,13 +125,13 @@ def to_lean_code(self, statement: LeanStatement) -> str:
129125
""".strip()
130126
return code
131127

132-
def verify_with_leandojo(self, statement: LeanStatement) -> Dict[str, Any]:
128+
def verify_with_leandojo(self, statement: LeanStatement) -> dict[str, Any]:
133129
"""Verify using LeanDojo (requires leandojo installation)."""
134130
if not self.use_leandojo:
135131
return {"status": "skipped", "reason": "LeanDojo disabled"}
136132

137133
try:
138-
lean_code = self.to_lean_code(statement)
134+
self.to_lean_code(statement)
139135
# LeanDojo API call would go here
140136
result = {
141137
"status": "verified",

tests/test_formal_verification.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414
PropertyType,
1515
build_claim_ir,
1616
)
17-
from formal_verification.hybrid_lean_coq_resolver import HybridLeanCoqResolver, ProverBackend
17+
from formal_verification.hybrid_lean_coq_resolver import (
18+
HybridLeanCoqResolver,
19+
ProverBackend,
20+
)
1821
from formal_verification.structured_models import PreservationAudit, PreservationLabel
1922

2023

@@ -608,26 +611,32 @@ class TestHybridLeanCoqResolver:
608611
"""Tests for the hybrid Lean/Coq fallback resolver."""
609612

610613
def test_try_coq_proof_wraps_proof_result_in_dict(self):
614+
"""Verify _try_coq_proof returns a dict wrapper around ProofResult."""
611615
resolver = HybridLeanCoqResolver()
612616
proof_result = ProofResult(None, True, 12.0, None, None, prover_name="coq")
613617

614-
with patch.object(resolver.coq_translator, "translate", return_value=Mock()) as mock_translate:
615-
with patch.object(resolver.coq_prover, "prove_specification", return_value=proof_result):
616-
result = resolver._try_coq_proof([("alice", "2 + 2 = 4", "correctness")])
618+
with (
619+
patch.object(resolver.coq_translator, "translate", return_value=Mock()) as mock_translate,
620+
patch.object(resolver.coq_prover, "prove_specification", return_value=proof_result),
621+
):
622+
result = resolver._try_coq_proof([("alice", "2 + 2 = 4", "correctness")])
617623

618624
assert result["proven"] is True
619625
assert result["result"] is proof_result
620626
assert result["error"] is None
621627
mock_translate.assert_called_once()
622628

623629
def test_resolve_conflict_uses_coq_fallback_without_dataclass_get(self):
630+
"""Verify Coq fallback when Lean proof fails."""
624631
resolver = HybridLeanCoqResolver(prefer_lean=True, use_fallback=True)
625632
failed_lean = Mock(proven=False)
626633
coq_result = {"proven": True, "result": ProofResult(None, True, 1.0, None, None)}
627634

628-
with patch.object(resolver, "_try_lean_proof", return_value=failed_lean):
629-
with patch.object(resolver, "_try_coq_proof", return_value=coq_result):
630-
result = resolver.resolve_conflict([("alice", "2 + 2 = 4", "correctness")])
635+
with (
636+
patch.object(resolver, "_try_lean_proof", return_value=failed_lean),
637+
patch.object(resolver, "_try_coq_proof", return_value=coq_result),
638+
):
639+
result = resolver.resolve_conflict([("alice", "2 + 2 = 4", "correctness")])
631640

632641
assert result.proven is True
633642
assert result.prover_used == ProverBackend.COQ

0 commit comments

Comments
 (0)