lean-interact 0.4.1__tar.gz → 0.5.0__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.5.0/.github/workflows/ci.yml +62 -0
- {lean_interact-0.4.1 → lean_interact-0.5.0}/PKG-INFO +20 -3
- {lean_interact-0.4.1 → lean_interact-0.5.0}/README.md +19 -1
- {lean_interact-0.4.1 → lean_interact-0.5.0}/pyproject.toml +1 -2
- {lean_interact-0.4.1 → lean_interact-0.5.0}/src/lean_interact/config.py +96 -34
- {lean_interact-0.4.1 → lean_interact-0.5.0}/src/lean_interact/interface.py +1 -1
- {lean_interact-0.4.1 → lean_interact-0.5.0}/src/lean_interact/server.py +143 -33
- {lean_interact-0.4.1 → lean_interact-0.5.0}/src/lean_interact/utils.py +118 -35
- lean_interact-0.5.0/tests/test_concurrency.py +429 -0
- {lean_interact-0.4.1 → lean_interact-0.5.0}/tests/test_server.py +156 -78
- {lean_interact-0.4.1 → lean_interact-0.5.0}/uv.lock +1 -3
- lean_interact-0.4.1/.github/workflows/ci.yml +0 -25
- lean_interact-0.4.1/tests/test_concurrency.py +0 -163
- {lean_interact-0.4.1 → lean_interact-0.5.0}/.devcontainer/devcontainer.json +0 -0
- {lean_interact-0.4.1 → lean_interact-0.5.0}/.github/workflows/publish-to-pypi.yml +0 -0
- {lean_interact-0.4.1 → lean_interact-0.5.0}/.gitignore +0 -0
- {lean_interact-0.4.1 → lean_interact-0.5.0}/LICENSE +0 -0
- {lean_interact-0.4.1 → lean_interact-0.5.0}/examples/beq_plus.py +0 -0
- {lean_interact-0.4.1 → lean_interact-0.5.0}/examples/proof_generation_and_autoformalization.py +0 -0
- {lean_interact-0.4.1 → lean_interact-0.5.0}/examples/type_check.py +0 -0
- {lean_interact-0.4.1 → lean_interact-0.5.0}/src/lean_interact/__init__.py +0 -0
- {lean_interact-0.4.1 → lean_interact-0.5.0}/tests/test_utils.py +0 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on: [push, pull_request]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
test:
|
|
7
|
+
name: Test on ${{ matrix.os }}
|
|
8
|
+
runs-on: ${{ matrix.os }}
|
|
9
|
+
strategy:
|
|
10
|
+
fail-fast: false
|
|
11
|
+
matrix:
|
|
12
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
13
|
+
python-version: ['3.10']
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- name: Configure Windows for long paths
|
|
17
|
+
if: runner.os == 'Windows'
|
|
18
|
+
shell: pwsh
|
|
19
|
+
run: |
|
|
20
|
+
# Enable long paths in registry
|
|
21
|
+
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
|
|
22
|
+
# Configure Git for long paths
|
|
23
|
+
git config --system core.longpaths true
|
|
24
|
+
|
|
25
|
+
- name: Checkout
|
|
26
|
+
uses: actions/checkout@v3
|
|
27
|
+
|
|
28
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
29
|
+
uses: actions/setup-python@v4
|
|
30
|
+
with:
|
|
31
|
+
python-version: ${{ matrix.python-version }}
|
|
32
|
+
|
|
33
|
+
- name: Install dependencies
|
|
34
|
+
run: |
|
|
35
|
+
python -m pip install --upgrade pip
|
|
36
|
+
python -m pip install .
|
|
37
|
+
|
|
38
|
+
- name: Install Lean (Linux/macOS)
|
|
39
|
+
if: runner.os != 'Windows'
|
|
40
|
+
run: |
|
|
41
|
+
install-lean
|
|
42
|
+
echo "$HOME/.elan/bin" >> $GITHUB_PATH
|
|
43
|
+
|
|
44
|
+
- name: Install Lean (Windows)
|
|
45
|
+
if: runner.os == 'Windows'
|
|
46
|
+
shell: pwsh
|
|
47
|
+
run: |
|
|
48
|
+
install-lean
|
|
49
|
+
echo "$env:USERPROFILE\.elan\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
|
50
|
+
|
|
51
|
+
- name: Run tests (Linux/macOS)
|
|
52
|
+
if: runner.os != 'Windows'
|
|
53
|
+
run: python -m unittest discover -s ./tests
|
|
54
|
+
env:
|
|
55
|
+
PYTHONIOENCODING: utf-8
|
|
56
|
+
|
|
57
|
+
- name: Run tests (Windows)
|
|
58
|
+
if: runner.os == 'Windows'
|
|
59
|
+
shell: pwsh
|
|
60
|
+
run: python -m unittest discover -s ./tests
|
|
61
|
+
env:
|
|
62
|
+
PYTHONIOENCODING: utf-8
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lean-interact
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
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
|
|
@@ -29,7 +29,6 @@ Keywords: Lean,REPL,autoformalization,theorem proving
|
|
|
29
29
|
Requires-Python: >=3.10
|
|
30
30
|
Requires-Dist: filelock>=3.18.0
|
|
31
31
|
Requires-Dist: gitpython>=3.1.44
|
|
32
|
-
Requires-Dist: pexpect>=4.9.0
|
|
33
32
|
Requires-Dist: psutil>=6.1.0
|
|
34
33
|
Requires-Dist: pydantic>=2.11.1
|
|
35
34
|
Requires-Dist: requests>=2.32.3
|
|
@@ -38,7 +37,8 @@ Description-Content-Type: text/markdown
|
|
|
38
37
|
|
|
39
38
|
# LeanInteract
|
|
40
39
|
|
|
41
|
-
[](https://pypi.org/project/lean-interact/)
|
|
41
|
+
[](https://pypi.org/project/lean-interact/)
|
|
42
42
|
[](https://www.python.org/downloads/)
|
|
43
43
|
[](https://opensource.org/licenses/MIT)
|
|
44
44
|
|
|
@@ -48,6 +48,7 @@ Description-Content-Type: text/markdown
|
|
|
48
48
|
|
|
49
49
|
- **🔗 Interactivity**: Execute Lean code and files directly from Python.
|
|
50
50
|
- **🚀 Ease of Use**: LeanInteract abstracts the complexities of Lean setup and interaction.
|
|
51
|
+
- **💻 Cross-platform**: Works on Windows, macOS, and Linux operating systems.
|
|
51
52
|
- **🔧 Compatibility**: Supports all Lean versions between `v4.7.0-rc1` and `v4.19.0-rc2`.
|
|
52
53
|
- We backport the latest features of Lean REPL to older versions of Lean.
|
|
53
54
|
- **📦 Temporary Projects**: Easily instantiate temporary Lean environments.
|
|
@@ -480,6 +481,22 @@ Common issues and their solutions:
|
|
|
480
481
|
|
|
481
482
|
3. **Long waiting times during first run**: This is expected as Lean REPL is being downloaded and built. Additionally, if you are importing Mathlib it will take even more time. Subsequent runs will be much faster.
|
|
482
483
|
|
|
484
|
+
4. **(Windows) Path too long error**: Windows has a maximum path length limitation of 260 characters.
|
|
485
|
+
If you get an error similar to the following one, you are likely affected by this problem:
|
|
486
|
+
|
|
487
|
+
```
|
|
488
|
+
error: external command 'git' exited with code 128
|
|
489
|
+
ERROR Failed during Lean project setup: Command '['lake', 'update']' returned non-zero exit status 1.
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
To resolve this, you can enable long paths in Windows 10 and later versions. For more information, refer to the [Microsoft documentation](https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation).
|
|
493
|
+
Alternatively, run the following command in a terminal with administrator privileges:
|
|
494
|
+
|
|
495
|
+
```bash
|
|
496
|
+
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name LongPathsEnabled -Value 1 -PropertyType DWord -Force
|
|
497
|
+
git config --system core.longpaths true
|
|
498
|
+
```
|
|
499
|
+
|
|
483
500
|
## Contributing
|
|
484
501
|
|
|
485
502
|
Contributions are welcome! Here's how you can help:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# LeanInteract
|
|
2
2
|
|
|
3
|
-
[](https://pypi.org/project/lean-interact/)
|
|
4
|
+
[](https://pypi.org/project/lean-interact/)
|
|
4
5
|
[](https://www.python.org/downloads/)
|
|
5
6
|
[](https://opensource.org/licenses/MIT)
|
|
6
7
|
|
|
@@ -10,6 +11,7 @@
|
|
|
10
11
|
|
|
11
12
|
- **🔗 Interactivity**: Execute Lean code and files directly from Python.
|
|
12
13
|
- **🚀 Ease of Use**: LeanInteract abstracts the complexities of Lean setup and interaction.
|
|
14
|
+
- **💻 Cross-platform**: Works on Windows, macOS, and Linux operating systems.
|
|
13
15
|
- **🔧 Compatibility**: Supports all Lean versions between `v4.7.0-rc1` and `v4.19.0-rc2`.
|
|
14
16
|
- We backport the latest features of Lean REPL to older versions of Lean.
|
|
15
17
|
- **📦 Temporary Projects**: Easily instantiate temporary Lean environments.
|
|
@@ -442,6 +444,22 @@ Common issues and their solutions:
|
|
|
442
444
|
|
|
443
445
|
3. **Long waiting times during first run**: This is expected as Lean REPL is being downloaded and built. Additionally, if you are importing Mathlib it will take even more time. Subsequent runs will be much faster.
|
|
444
446
|
|
|
447
|
+
4. **(Windows) Path too long error**: Windows has a maximum path length limitation of 260 characters.
|
|
448
|
+
If you get an error similar to the following one, you are likely affected by this problem:
|
|
449
|
+
|
|
450
|
+
```
|
|
451
|
+
error: external command 'git' exited with code 128
|
|
452
|
+
ERROR Failed during Lean project setup: Command '['lake', 'update']' returned non-zero exit status 1.
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
To resolve this, you can enable long paths in Windows 10 and later versions. For more information, refer to the [Microsoft documentation](https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation).
|
|
456
|
+
Alternatively, run the following command in a terminal with administrator privileges:
|
|
457
|
+
|
|
458
|
+
```bash
|
|
459
|
+
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name LongPathsEnabled -Value 1 -PropertyType DWord -Force
|
|
460
|
+
git config --system core.longpaths true
|
|
461
|
+
```
|
|
462
|
+
|
|
445
463
|
## Contributing
|
|
446
464
|
|
|
447
465
|
Contributions are welcome! Here's how you can help:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "lean-interact"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.5.0"
|
|
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" }
|
|
@@ -10,7 +10,6 @@ requires-python = ">=3.10"
|
|
|
10
10
|
dependencies = [
|
|
11
11
|
"filelock>=3.18.0",
|
|
12
12
|
"gitpython>=3.1.44",
|
|
13
|
-
"pexpect>=4.9.0",
|
|
14
13
|
"psutil>=6.1.0",
|
|
15
14
|
"pydantic>=2.11.1",
|
|
16
15
|
"requests>=2.32.3",
|
|
@@ -58,8 +58,11 @@ class LocalProject(BaseProject):
|
|
|
58
58
|
stderr = None if verbose else subprocess.DEVNULL
|
|
59
59
|
|
|
60
60
|
with FileLock(f"{self.directory}.lock"):
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
try:
|
|
62
|
+
subprocess.run(["lake", "build"], cwd=self.directory, check=True, stdout=stdout, stderr=stderr)
|
|
63
|
+
except subprocess.CalledProcessError as e:
|
|
64
|
+
logger.error("Failed to build local project: %s", e)
|
|
65
|
+
raise
|
|
63
66
|
|
|
64
67
|
|
|
65
68
|
@dataclass(frozen=True)
|
|
@@ -70,8 +73,15 @@ class GitProject(BaseProject):
|
|
|
70
73
|
rev: str | None = None
|
|
71
74
|
|
|
72
75
|
def _get_directory(self, cache_dir: str, lean_version: str | None = None) -> str:
|
|
73
|
-
|
|
74
|
-
|
|
76
|
+
repo_parts = self.url.split("/")
|
|
77
|
+
if len(repo_parts) >= 2:
|
|
78
|
+
owner = repo_parts[-2]
|
|
79
|
+
repo = repo_parts[-1].replace(".git", "")
|
|
80
|
+
return os.path.join(cache_dir, "git_projects", owner, repo, self.rev or "latest")
|
|
81
|
+
else:
|
|
82
|
+
# Fallback for malformed URLs
|
|
83
|
+
repo_name = self.url.replace(".git", "").split("/")[-1]
|
|
84
|
+
return os.path.join(cache_dir, "git_projects", repo_name, self.rev or "latest")
|
|
75
85
|
|
|
76
86
|
def _instantiate(self, cache_dir: str, lean_version: str, verbose: bool = True):
|
|
77
87
|
"""Instantiate the git project."""
|
|
@@ -91,8 +101,11 @@ class GitProject(BaseProject):
|
|
|
91
101
|
|
|
92
102
|
repo.submodule_update(init=True, recursive=True)
|
|
93
103
|
|
|
94
|
-
|
|
95
|
-
|
|
104
|
+
try:
|
|
105
|
+
subprocess.run(["lake", "build"], cwd=project_dir, check=True, stdout=stdout, stderr=stderr)
|
|
106
|
+
except subprocess.CalledProcessError as e:
|
|
107
|
+
logger.error("Failed to build the git project: %s", e)
|
|
108
|
+
raise
|
|
96
109
|
|
|
97
110
|
|
|
98
111
|
@dataclass(frozen=True)
|
|
@@ -117,8 +130,8 @@ class BaseTempProject(BaseProject):
|
|
|
117
130
|
|
|
118
131
|
# Lock the temporary project directory during setup
|
|
119
132
|
with FileLock(f"{tmp_project_dir}.lock"):
|
|
120
|
-
# check if the Lean project
|
|
121
|
-
if not os.path.exists(os.path.join(tmp_project_dir, "
|
|
133
|
+
# check if the Lean project already exists
|
|
134
|
+
if not os.path.exists(os.path.join(tmp_project_dir, "lake-manifest.json")):
|
|
122
135
|
# clean the content of the folder in case of a previous aborted build
|
|
123
136
|
shutil.rmtree(tmp_project_dir, ignore_errors=True)
|
|
124
137
|
os.makedirs(tmp_project_dir, exist_ok=True)
|
|
@@ -127,16 +140,31 @@ class BaseTempProject(BaseProject):
|
|
|
127
140
|
cmd_init = ["lake", f"+{lean_version}", "init", "dummy", "exe.lean"]
|
|
128
141
|
if lean_version.startswith("v4") and int(lean_version.split(".")[1]) <= 7:
|
|
129
142
|
cmd_init = ["lake", f"+{lean_version}", "init", "dummy", "exe"]
|
|
130
|
-
|
|
143
|
+
|
|
144
|
+
try:
|
|
145
|
+
subprocess.run(cmd_init, cwd=tmp_project_dir, check=True, stdout=stdout, stderr=stderr)
|
|
146
|
+
except subprocess.CalledProcessError as e:
|
|
147
|
+
logger.error("Failed to initialize Lean project: %s", e)
|
|
148
|
+
raise
|
|
131
149
|
|
|
132
150
|
# Create or modify the lakefile
|
|
133
151
|
self._modify_lakefile(tmp_project_dir, lean_version)
|
|
134
152
|
|
|
135
153
|
logger.info("Preparing Lean environment with dependencies (may take a while the first time)...")
|
|
136
|
-
|
|
137
|
-
#
|
|
138
|
-
|
|
139
|
-
|
|
154
|
+
|
|
155
|
+
# Run lake commands with appropriate platform handling
|
|
156
|
+
try:
|
|
157
|
+
subprocess.run(["lake", "update"], cwd=tmp_project_dir, check=True, stdout=stdout, stderr=stderr)
|
|
158
|
+
# in case mathlib is used as a dependency, we try to get the cache
|
|
159
|
+
subprocess.run(
|
|
160
|
+
["lake", "exe", "cache", "get"], cwd=tmp_project_dir, check=False, stdout=stdout, stderr=stderr
|
|
161
|
+
)
|
|
162
|
+
subprocess.run(["lake", "build"], cwd=tmp_project_dir, check=True, stdout=stdout, stderr=stderr)
|
|
163
|
+
except subprocess.CalledProcessError as e:
|
|
164
|
+
logger.error("Failed during Lean project setup: %s", e)
|
|
165
|
+
# delete the project directory to avoid conflicts
|
|
166
|
+
shutil.rmtree(tmp_project_dir, ignore_errors=True)
|
|
167
|
+
raise
|
|
140
168
|
|
|
141
169
|
def _get_hash_content(self, lean_version: str) -> str:
|
|
142
170
|
"""Return a unique hash for the project content."""
|
|
@@ -159,7 +187,7 @@ class TemporaryProject(BaseTempProject):
|
|
|
159
187
|
|
|
160
188
|
def _modify_lakefile(self, project_dir: str, lean_version: str) -> None:
|
|
161
189
|
"""Write the content to the lakefile."""
|
|
162
|
-
with open(os.path.join(project_dir, "lakefile.lean"), "w") as f:
|
|
190
|
+
with open(os.path.join(project_dir, "lakefile.lean"), "w", encoding="utf-8") as f:
|
|
163
191
|
f.write(self.content)
|
|
164
192
|
|
|
165
193
|
|
|
@@ -173,15 +201,26 @@ class TempRequireProject(BaseTempProject):
|
|
|
173
201
|
[MiniF2F](https://github.com/yangky11/miniF2F-lean4)) without having to manually set up a Lean project.
|
|
174
202
|
"""
|
|
175
203
|
|
|
176
|
-
require: Literal["mathlib"] | list[LeanRequire]
|
|
204
|
+
require: Literal["mathlib"] | LeanRequire | list[LeanRequire | Literal["mathlib"]]
|
|
177
205
|
|
|
178
206
|
def _normalize_require(self, lean_version: str) -> list[LeanRequire]:
|
|
179
207
|
"""Normalize the require field to always be a list."""
|
|
180
208
|
require = self.require
|
|
181
|
-
if require
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
209
|
+
if not isinstance(require, list):
|
|
210
|
+
require = [require]
|
|
211
|
+
|
|
212
|
+
normalized_require: list[LeanRequire] = []
|
|
213
|
+
for req in require:
|
|
214
|
+
if req == "mathlib":
|
|
215
|
+
normalized_require.append(
|
|
216
|
+
LeanRequire("mathlib", "https://github.com/leanprover-community/mathlib4.git", lean_version)
|
|
217
|
+
)
|
|
218
|
+
elif isinstance(req, LeanRequire):
|
|
219
|
+
normalized_require.append(req)
|
|
220
|
+
else:
|
|
221
|
+
raise ValueError(f"Invalid requirement type: {type(req)}")
|
|
222
|
+
|
|
223
|
+
return sorted(normalized_require, key=lambda x: x.name)
|
|
185
224
|
|
|
186
225
|
def _get_hash_content(self, lean_version: str) -> str:
|
|
187
226
|
"""Return a unique hash based on dependencies."""
|
|
@@ -191,7 +230,7 @@ class TempRequireProject(BaseTempProject):
|
|
|
191
230
|
def _modify_lakefile(self, project_dir: str, lean_version: str) -> None:
|
|
192
231
|
"""Add requirements to the lakefile."""
|
|
193
232
|
require = self._normalize_require(lean_version)
|
|
194
|
-
with open(os.path.join(project_dir, "lakefile.lean"), "a") as f:
|
|
233
|
+
with open(os.path.join(project_dir, "lakefile.lean"), "a", encoding="utf-8") as f:
|
|
195
234
|
for req in require:
|
|
196
235
|
f.write(f'\n\nrequire {req.name} from git\n "{req.git}"' + (f' @ "{req.rev}"' if req.rev else ""))
|
|
197
236
|
|
|
@@ -208,16 +247,18 @@ class LeanREPLConfig:
|
|
|
208
247
|
verbose: bool = False,
|
|
209
248
|
):
|
|
210
249
|
"""
|
|
211
|
-
|
|
250
|
+
Initialize the Lean REPL configuration.
|
|
212
251
|
|
|
213
252
|
Args:
|
|
214
|
-
lean_version:
|
|
215
|
-
|
|
216
|
-
the latest version
|
|
217
|
-
project:
|
|
218
|
-
|
|
219
|
-
- `
|
|
220
|
-
- `
|
|
253
|
+
lean_version:
|
|
254
|
+
The Lean version you want to use.
|
|
255
|
+
Default is `None`, which means the latest version compatible with the project will be selected.
|
|
256
|
+
project:
|
|
257
|
+
The project you want to use. There are 4 options:
|
|
258
|
+
- `None`: The project will only depend on Lean and its standard library.
|
|
259
|
+
- `LocalProject`: An existing local Lean project.
|
|
260
|
+
- `GitProject`: A git repository with a Lean project that will be cloned.
|
|
261
|
+
- `TemporaryProject`: A temporary Lean project with a custom lakefile.lean that will be created.
|
|
221
262
|
- `TempRequireProject`: A temporary Lean project with dependencies that will be created.
|
|
222
263
|
repl_rev:
|
|
223
264
|
The REPL version you want to use. It is not recommended to change this value unless you know what you are doing.
|
|
@@ -228,6 +269,7 @@ class LeanREPLConfig:
|
|
|
228
269
|
Default is inside the package directory.
|
|
229
270
|
memory_hard_limit_mb:
|
|
230
271
|
The maximum memory usage in MB for the Lean server. Setting this value too low may lead to more command processing failures.
|
|
272
|
+
Only available on Linux platforms.
|
|
231
273
|
Default is `None`, which means no limit.
|
|
232
274
|
verbose:
|
|
233
275
|
Whether to print additional information during the setup process.
|
|
@@ -236,14 +278,21 @@ class LeanREPLConfig:
|
|
|
236
278
|
self.project = project
|
|
237
279
|
self.repl_git = repl_git
|
|
238
280
|
self.repl_rev = repl_rev
|
|
239
|
-
self.cache_dir = cache_dir
|
|
281
|
+
self.cache_dir = os.path.normpath(cache_dir)
|
|
240
282
|
self.memory_hard_limit_mb = memory_hard_limit_mb
|
|
241
283
|
|
|
242
284
|
self.verbose = verbose
|
|
243
285
|
self._stdout = None if self.verbose else subprocess.DEVNULL
|
|
244
286
|
self._stderr = None if self.verbose else subprocess.DEVNULL
|
|
245
287
|
|
|
246
|
-
|
|
288
|
+
repo_parts = self.repl_git.split("/")
|
|
289
|
+
if len(repo_parts) >= 2:
|
|
290
|
+
owner = repo_parts[-2]
|
|
291
|
+
repo = repo_parts[-1].replace(".git", "")
|
|
292
|
+
self.repo_name = os.path.join(owner, repo)
|
|
293
|
+
else:
|
|
294
|
+
self.repo_name = self.repl_git.replace(".git", "")
|
|
295
|
+
|
|
247
296
|
self.cache_clean_repl_dir = os.path.join(self.cache_dir, self.repo_name, "repl_clean_copy")
|
|
248
297
|
|
|
249
298
|
# check if lake is installed
|
|
@@ -322,10 +371,13 @@ class LeanREPLConfig:
|
|
|
322
371
|
f"Please open an issue on GitHub if you think this is a bug."
|
|
323
372
|
)
|
|
324
373
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
374
|
+
try:
|
|
375
|
+
subprocess.run(
|
|
376
|
+
["lake", "build"], cwd=self._cache_repl_dir, check=True, stdout=self._stdout, stderr=self._stderr
|
|
377
|
+
)
|
|
378
|
+
except subprocess.CalledProcessError as e:
|
|
379
|
+
logger.error("Failed to build the REPL: %s", e)
|
|
380
|
+
raise
|
|
329
381
|
|
|
330
382
|
def _get_available_lean_versions_sha(self) -> list[tuple[str, str]]:
|
|
331
383
|
"""
|
|
@@ -344,5 +396,15 @@ class LeanREPLConfig:
|
|
|
344
396
|
"""
|
|
345
397
|
return [commit[0] for commit in self._get_available_lean_versions_sha()]
|
|
346
398
|
|
|
399
|
+
@property
|
|
400
|
+
def working_dir(self) -> str:
|
|
401
|
+
"""Get the working directory for the Lean environment."""
|
|
402
|
+
return self._working_dir
|
|
403
|
+
|
|
404
|
+
@property
|
|
405
|
+
def cache_repl_dir(self) -> str:
|
|
406
|
+
"""Get the cache directory for the Lean REPL."""
|
|
407
|
+
return self._cache_repl_dir
|
|
408
|
+
|
|
347
409
|
def is_setup(self) -> bool:
|
|
348
410
|
return hasattr(self, "_working_dir")
|