lean-interact 0.8.2__tar.gz → 0.8.3__tar.gz
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.
- {lean_interact-0.8.2 → lean_interact-0.8.3}/.gitignore +4 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/PKG-INFO +2 -2
- {lean_interact-0.8.2 → lean_interact-0.8.3}/README.md +1 -1
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/index.md +1 -1
- {lean_interact-0.8.2 → lean_interact-0.8.3}/pyproject.toml +1 -1
- {lean_interact-0.8.2 → lean_interact-0.8.3}/src/lean_interact/config.py +18 -7
- {lean_interact-0.8.2 → lean_interact-0.8.3}/src/lean_interact/server.py +25 -9
- {lean_interact-0.8.2 → lean_interact-0.8.3}/src/lean_interact/utils.py +16 -5
- {lean_interact-0.8.2 → lean_interact-0.8.3}/tests/test_server.py +4 -0
- lean_interact-0.8.2/uv.lock +0 -1825
- {lean_interact-0.8.2 → lean_interact-0.8.3}/.devcontainer/devcontainer.json +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/.github/copilot-instructions.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/.github/workflows/ci.yml +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/.github/workflows/docs.yml +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/.github/workflows/publish-to-pypi.yml +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/LICENSE +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/.nojekyll +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/api/config.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/api/interface.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/api/project.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/api/server.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/api/sessioncache.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/api/utils.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/contributing.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/generate_changelog.py +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/theme/main.html +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/user-guide/basic-usage.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/user-guide/custom-lean-configuration.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/user-guide/examples.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/user-guide/getting-started.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/user-guide/installation.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/user-guide/multi-processing.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/user-guide/tactic-mode.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/docs/user-guide/troubleshooting.md +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/examples/beq_plus.py +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/examples/multi_processing.py +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/examples/proof_generation_and_autoformalization.py +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/examples/type_check.py +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/mkdocs.yml +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/src/lean_interact/__init__.py +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/src/lean_interact/interface.py +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/src/lean_interact/project.py +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/src/lean_interact/sessioncache.py +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/tests/test_concurrency.py +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/tests/test_git_functionality.py +0 -0
- {lean_interact-0.8.2 → lean_interact-0.8.3}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lean-interact
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.3
|
|
4
4
|
Summary: LeanInteract is a Python package that allows you to interact with the Lean theorem prover.
|
|
5
5
|
Author-email: Auguste Poiroux <auguste.poiroux@epfl.ch>
|
|
6
6
|
License: MIT License
|
|
@@ -53,7 +53,7 @@ Check the [documentation](https://augustepoiroux.github.io/LeanInteract/) for de
|
|
|
53
53
|
- **🔗 Interactivity**: Execute Lean code and files directly from Python.
|
|
54
54
|
- **🚀 Ease of Use**: LeanInteract abstracts the complexities of Lean setup and interaction.
|
|
55
55
|
- **💻 Cross-platform**: Works on Windows, macOS, and Linux operating systems.
|
|
56
|
-
- **🔧 Compatibility**: Supports all Lean versions between `v4.7.0-rc1` and `v4.
|
|
56
|
+
- **🔧 Compatibility**: Supports all Lean versions between `v4.7.0-rc1` and `v4.24.0-rc1`.
|
|
57
57
|
- We backport the latest features of Lean REPL to older versions of Lean (see [fork](https://github.com/augustepoiroux/repl)).
|
|
58
58
|
- **📦 Temporary Projects**: Easily instantiate temporary Lean environments.
|
|
59
59
|
- Useful for experimenting with benchmarks depending on [Mathlib](https://github.com/leanprover-community/mathlib4) like [ProofNet#](https://huggingface.co/datasets/PAug/ProofNetSharp) and [MiniF2F](https://github.com/yangky11/miniF2F-lean4).
|
|
@@ -15,7 +15,7 @@ Check the [documentation](https://augustepoiroux.github.io/LeanInteract/) for de
|
|
|
15
15
|
- **🔗 Interactivity**: Execute Lean code and files directly from Python.
|
|
16
16
|
- **🚀 Ease of Use**: LeanInteract abstracts the complexities of Lean setup and interaction.
|
|
17
17
|
- **💻 Cross-platform**: Works on Windows, macOS, and Linux operating systems.
|
|
18
|
-
- **🔧 Compatibility**: Supports all Lean versions between `v4.7.0-rc1` and `v4.
|
|
18
|
+
- **🔧 Compatibility**: Supports all Lean versions between `v4.7.0-rc1` and `v4.24.0-rc1`.
|
|
19
19
|
- We backport the latest features of Lean REPL to older versions of Lean (see [fork](https://github.com/augustepoiroux/repl)).
|
|
20
20
|
- **📦 Temporary Projects**: Easily instantiate temporary Lean environments.
|
|
21
21
|
- Useful for experimenting with benchmarks depending on [Mathlib](https://github.com/leanprover-community/mathlib4) like [ProofNet#](https://huggingface.co/datasets/PAug/ProofNetSharp) and [MiniF2F](https://github.com/yangky11/miniF2F-lean4).
|
|
@@ -17,7 +17,7 @@ hide:
|
|
|
17
17
|
- **🔗 Interactivity**: Execute Lean code and files directly from Python
|
|
18
18
|
- **🚀 Ease of Use**: LeanInteract abstracts the complexities of Lean setup and interaction
|
|
19
19
|
- **💻 Cross-platform**: Works on Windows, macOS, and Linux operating systems
|
|
20
|
-
- **🔧 Compatibility**: Supports all Lean versions between `v4.7.0-rc1` and `v4.
|
|
20
|
+
- **🔧 Compatibility**: Supports all Lean versions between `v4.7.0-rc1` and `v4.24.0-rc1`
|
|
21
21
|
- We backport the latest features of Lean REPL to older versions of Lean (see [fork](https://github.com/augustepoiroux/repl)).
|
|
22
22
|
- **📦 Temporary Projects**: Easily instantiate temporary Lean environments
|
|
23
23
|
- Useful for experimenting with benchmarks depending on [Mathlib](https://github.com/leanprover-community/mathlib4) like [ProofNet#](https://huggingface.co/datasets/PAug/ProofNetSharp) and [MiniF2F](https://github.com/yangky11/miniF2F-lean4)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "lean-interact"
|
|
3
|
-
version = "0.8.
|
|
3
|
+
version = "0.8.3"
|
|
4
4
|
description = "LeanInteract is a Python package that allows you to interact with the Lean theorem prover."
|
|
5
5
|
keywords = ["Lean", "theorem proving", "autoformalization", "REPL"]
|
|
6
6
|
license = { file = "LICENSE" }
|
|
@@ -383,16 +383,27 @@ class LeanREPLConfig:
|
|
|
383
383
|
check_lake(self.lake_path)
|
|
384
384
|
|
|
385
385
|
try:
|
|
386
|
-
|
|
386
|
+
# Capture build output so failures can be diagnosed
|
|
387
|
+
res = subprocess.run(
|
|
387
388
|
[str(self.lake_path), "build"],
|
|
388
389
|
cwd=self._cache_repl_dir,
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
390
|
+
stdout=None if self.verbose else subprocess.PIPE,
|
|
391
|
+
stderr=None if self.verbose else subprocess.PIPE,
|
|
392
|
+
text=True,
|
|
393
|
+
)
|
|
394
|
+
except FileNotFoundError as e:
|
|
395
|
+
raise RuntimeError(
|
|
396
|
+
f"Lean 4 build system executable not found at `{self.lake_path}`. "
|
|
397
|
+
"You can try to run `install-lean` or follow: https://leanprover-community.github.io/get_started.html"
|
|
398
|
+
) from e
|
|
399
|
+
|
|
400
|
+
if res.returncode != 0:
|
|
401
|
+
out = res.stdout or ""
|
|
402
|
+
err = res.stderr or ""
|
|
403
|
+
raise RuntimeError(
|
|
404
|
+
f"Failed to build the REPL at {self._cache_repl_dir}"
|
|
405
|
+
f"\n{'-' * 50}\nstdout:\n{out}\n{'-' * 50}\nstderr:\n{err}\n{'-' * 50}"
|
|
392
406
|
)
|
|
393
|
-
except subprocess.CalledProcessError as e:
|
|
394
|
-
logger.error("Failed to build the REPL at %s: %s", self._cache_repl_dir, e)
|
|
395
|
-
raise
|
|
396
407
|
|
|
397
408
|
def _get_available_lean_versions(self) -> list[tuple[str, str | None]]:
|
|
398
409
|
"""
|
|
@@ -88,6 +88,19 @@ class LeanServer:
|
|
|
88
88
|
if platform.system() != "Linux"
|
|
89
89
|
else lambda: _limit_memory(self.config.memory_hard_limit_mb),
|
|
90
90
|
)
|
|
91
|
+
if not self.is_alive():
|
|
92
|
+
stdout, stderr = self.get_stdout_stderr()
|
|
93
|
+
raise ChildProcessError(f"The Lean server could not be started:\nstdout: {stdout}\nstderr: {stderr}")
|
|
94
|
+
|
|
95
|
+
def get_stdout_stderr(self) -> tuple[str, str]:
|
|
96
|
+
"""Get the stdout and stderr output from the Lean REPL.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
A tuple containing the stdout and stderr output.
|
|
100
|
+
"""
|
|
101
|
+
stdout = self._proc.stdout.read() if self._proc and self._proc.stdout else ""
|
|
102
|
+
stderr = self._proc.stderr.read() if self._proc and self._proc.stderr else ""
|
|
103
|
+
return stdout, stderr
|
|
91
104
|
|
|
92
105
|
def _sendline(self, line: str) -> None:
|
|
93
106
|
assert self._proc is not None and self._proc.stdin is not None
|
|
@@ -199,11 +212,9 @@ class LeanServer:
|
|
|
199
212
|
if t.is_alive():
|
|
200
213
|
self.kill()
|
|
201
214
|
raise TimeoutError(f"The Lean server did not respond in time ({timeout=}) and is now killed.")
|
|
202
|
-
if output:
|
|
215
|
+
if output.strip():
|
|
203
216
|
return output
|
|
204
|
-
|
|
205
|
-
raise BrokenPipeError("The Lean server returned no output.")
|
|
206
|
-
raise BrokenPipeError(f"The Lean server closed unexpectedly with the output:\n`{output}`")
|
|
217
|
+
raise BrokenPipeError("The Lean server returned no output.")
|
|
207
218
|
|
|
208
219
|
def _parse_repl_output(self, raw_output: str, verbose: bool) -> dict:
|
|
209
220
|
"""Parse JSON response.
|
|
@@ -258,7 +269,10 @@ class LeanServer:
|
|
|
258
269
|
JsonDecodeError: If the Lean server output is not valid JSON.
|
|
259
270
|
"""
|
|
260
271
|
if not self.is_alive():
|
|
261
|
-
|
|
272
|
+
stdout, stderr = self.get_stdout_stderr()
|
|
273
|
+
raise ChildProcessError(
|
|
274
|
+
f"The Lean server is not running.\n{'-' * 50}\nstdout:\n{stdout}\n{'-' * 50}\nstderr:\n{stderr}\n{'-' * 50}"
|
|
275
|
+
)
|
|
262
276
|
|
|
263
277
|
json_query = json.dumps(request, ensure_ascii=False)
|
|
264
278
|
try:
|
|
@@ -267,13 +281,15 @@ class LeanServer:
|
|
|
267
281
|
self.kill()
|
|
268
282
|
raise TimeoutError(f"The Lean server did not respond in time ({timeout=}) and is now killed.") from e
|
|
269
283
|
except BrokenPipeError as e:
|
|
284
|
+
stdout, stderr = self.get_stdout_stderr()
|
|
270
285
|
self.kill()
|
|
271
286
|
raise ConnectionAbortedError(
|
|
272
|
-
"The Lean server closed unexpectedly.
|
|
273
|
-
"-
|
|
287
|
+
f"The Lean server closed unexpectedly."
|
|
288
|
+
f"\n{'-' * 50}\nstdout:\n{stdout}\n{'-' * 50}\nstderr:\n{stderr}\n{'-' * 50}"
|
|
289
|
+
f"If stdout and stderr are empty or obscure, here is a list of possible reasons (not exhaustive):\n"
|
|
274
290
|
"- Not enough memory and/or compute available\n"
|
|
275
|
-
"- The cached Lean REPL is corrupted. In this case, clear the cache"
|
|
276
|
-
"
|
|
291
|
+
"- The cached Lean REPL is corrupted. In this case, clear the cache using the `clear-lean-cache` command.\n"
|
|
292
|
+
"- An uncaught exception in the Lean REPL"
|
|
277
293
|
) from e
|
|
278
294
|
|
|
279
295
|
return self._parse_repl_output(raw_output, verbose)
|
|
@@ -22,7 +22,7 @@ logger.addHandler(handler)
|
|
|
22
22
|
ROOT_DIR = Path(__file__).resolve().parent
|
|
23
23
|
DEFAULT_CACHE_DIR = ROOT_DIR / "cache"
|
|
24
24
|
DEFAULT_REPL_GIT_URL = "https://github.com/augustepoiroux/repl"
|
|
25
|
-
DEFAULT_REPL_VERSION = "v1.0.
|
|
25
|
+
DEFAULT_REPL_VERSION = "v1.0.16"
|
|
26
26
|
|
|
27
27
|
os.makedirs(DEFAULT_CACHE_DIR, exist_ok=True)
|
|
28
28
|
|
|
@@ -92,11 +92,22 @@ def check_lake(lake_path: str | PathLike) -> None:
|
|
|
92
92
|
lake_path = Path(lake_path)
|
|
93
93
|
|
|
94
94
|
try:
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
result = subprocess.run(
|
|
96
|
+
[str(lake_path), "--version"],
|
|
97
|
+
stdout=subprocess.PIPE,
|
|
98
|
+
stderr=subprocess.PIPE,
|
|
99
|
+
text=True,
|
|
100
|
+
)
|
|
101
|
+
except FileNotFoundError as e:
|
|
102
|
+
raise RuntimeError(
|
|
103
|
+
f"Lean 4 build system executable not found at `{lake_path}`: {e}. "
|
|
104
|
+
"You can try to run `install-lean` or follow: https://leanprover-community.github.io/get_started.html"
|
|
105
|
+
) from e
|
|
106
|
+
|
|
107
|
+
if result.returncode != 0:
|
|
97
108
|
raise RuntimeError(
|
|
98
|
-
f"Lean 4 build system (`{lake_path}`)
|
|
99
|
-
"
|
|
109
|
+
f"Lean 4 build system (`{lake_path}`) failed with exit code {result.returncode}.\n"
|
|
110
|
+
f"stdout:\n{result.stdout}\n\nstderr:\n{result.stderr}"
|
|
100
111
|
)
|
|
101
112
|
|
|
102
113
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import platform
|
|
3
3
|
import shutil
|
|
4
|
+
import subprocess
|
|
4
5
|
import tempfile
|
|
5
6
|
import time
|
|
6
7
|
import unittest
|
|
@@ -120,6 +121,9 @@ class TestLeanServer(unittest.TestCase):
|
|
|
120
121
|
self.assertIsInstance(response, CommandResponse)
|
|
121
122
|
# Re-use the existing build
|
|
122
123
|
with unittest.mock.patch("subprocess.run") as run_mock:
|
|
124
|
+
run_mock.return_value = subprocess.CompletedProcess(
|
|
125
|
+
args=["lake", "--version"], returncode=0, stdout="", stderr=""
|
|
126
|
+
)
|
|
123
127
|
new_config = LeanREPLConfig(
|
|
124
128
|
project=LocalProject(directory=base_config.working_dir, auto_build=False), verbose=True
|
|
125
129
|
)
|