tlaplus-cli 0.3.5__tar.gz → 0.4.2__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.
- {tlaplus_cli-0.3.5/src/tlaplus_cli.egg-info → tlaplus_cli-0.4.2}/PKG-INFO +29 -3
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/README.md +28 -2
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/pyproject.toml +7 -2
- tlaplus_cli-0.4.2/src/tlaplus_cli/cache/github.py +28 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cli.py +60 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/__init__.py +0 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/check_java.py +19 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/config/__init__.py +6 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/config/edit.py +34 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/config/list.py +16 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/fetch_cache/__init__.py +5 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/fetch_cache/clear.py +11 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/modules/__init__.py +5 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/modules/build.py +30 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/modules/lib.py +46 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/modules/path.py +39 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/tlc.py +51 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/tools/__init__.py +8 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/tools/dir.py +16 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/tools/install.py +79 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/tools/list.py +80 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/tools/meta/__init__.py +5 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/tools/meta/sync.py +33 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/tools/path.py +33 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/tools/pin.py +31 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/tools/uninstall.py +103 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/cmd/tools/upgrade.py +76 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/config/__init__.py +0 -0
- tlaplus_cli-0.3.5/src/tlaplus_cli/config.py → tlaplus_cli-0.4.2/src/tlaplus_cli/config/loader.py +3 -3
- tlaplus_cli-0.3.5/src/tlaplus_cli/settings.py → tlaplus_cli-0.4.2/src/tlaplus_cli/config/schema.py +1 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/java/__init__.py +7 -0
- tlaplus_cli-0.3.5/src/tlaplus_cli/check_java.py → tlaplus_cli-0.4.2/src/tlaplus_cli/java/inspector.py +15 -11
- tlaplus_cli-0.4.2/src/tlaplus_cli/project/__init__.py +3 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/py.typed +0 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/tlc/__init__.py +0 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/tlc/compiler.py +88 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/tlc/runner.py +102 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/ui.py +6 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/versioning/__init__.py +53 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/versioning/api.py +110 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/versioning/downloader.py +93 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/versioning/metadata.py +92 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/versioning/paths.py +83 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/versioning/resolver.py +92 -0
- tlaplus_cli-0.4.2/src/tlaplus_cli/versioning/schema.py +27 -0
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2/src/tlaplus_cli.egg-info}/PKG-INFO +29 -3
- tlaplus_cli-0.4.2/src/tlaplus_cli.egg-info/SOURCES.txt +67 -0
- tlaplus_cli-0.4.2/tests/test_build_both.py +32 -0
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/tests/test_build_modules_path.py +5 -5
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/tests/test_config.py +7 -47
- tlaplus_cli-0.4.2/tests/test_config_suite.py +74 -0
- tlaplus_cli-0.4.2/tests/test_modules_build_lib.py +88 -0
- tlaplus_cli-0.4.2/tests/test_modules_lib.py +106 -0
- tlaplus_cli-0.4.2/tests/test_modules_path.py +101 -0
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/tests/test_settings.py +1 -1
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/tests/test_tlc_modules_path.py +5 -5
- tlaplus_cli-0.3.5/src/tlaplus_cli/build_tlc_module.py +0 -86
- tlaplus_cli-0.3.5/src/tlaplus_cli/cli.py +0 -76
- tlaplus_cli-0.3.5/src/tlaplus_cli/run_tlc.py +0 -120
- tlaplus_cli-0.3.5/src/tlaplus_cli/tools_manager.py +0 -385
- tlaplus_cli-0.3.5/src/tlaplus_cli/version_manager.py +0 -502
- tlaplus_cli-0.3.5/src/tlaplus_cli.egg-info/SOURCES.txt +0 -29
- tlaplus_cli-0.3.5/tests/test_modules_path.py +0 -62
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/LICENSE +0 -0
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/MANIFEST.in +0 -0
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/setup.cfg +0 -0
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/src/tlaplus_cli/__init__.py +0 -0
- /tlaplus_cli-0.3.5/src/tlaplus_cli/py.typed → /tlaplus_cli-0.4.2/src/tlaplus_cli/cache/__init__.py +0 -0
- /tlaplus_cli-0.3.5/src/tlaplus_cli/project.py → /tlaplus_cli-0.4.2/src/tlaplus_cli/project/core.py +0 -0
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/src/tlaplus_cli/resources/__init__.py +0 -0
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/src/tlaplus_cli/resources/default_config.yaml +0 -0
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/src/tlaplus_cli.egg-info/dependency_links.txt +0 -0
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/src/tlaplus_cli.egg-info/entry_points.txt +0 -0
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/src/tlaplus_cli.egg-info/requires.txt +0 -0
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/src/tlaplus_cli.egg-info/top_level.txt +0 -0
- {tlaplus_cli-0.3.5 → tlaplus_cli-0.4.2}/tests/test_cli.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tlaplus-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: TLA+ tools: download TLC, compile custom modules, run model checker
|
|
5
5
|
Author-email: Denis Nikolskiy <codeomatics@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -175,8 +175,25 @@ Configure a persistent custom modules path:
|
|
|
175
175
|
tla modules path /path/to/custom/modules
|
|
176
176
|
```
|
|
177
177
|
|
|
178
|
+
View or reset the custom modules path:
|
|
179
|
+
```bash
|
|
180
|
+
tla modules path # View current path
|
|
181
|
+
tla modules path none # Reset to default
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Configure a persistent custom modules dependencies (lib) path:
|
|
185
|
+
```bash
|
|
186
|
+
tla modules lib /path/to/custom/libs
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
View or reset the custom lib path:
|
|
190
|
+
```bash
|
|
191
|
+
tla modules lib # View current path
|
|
192
|
+
tla modules lib none # Reset to default
|
|
193
|
+
```
|
|
194
|
+
|
|
178
195
|
> [!TIP]
|
|
179
|
-
> Setting a persistent `module_path` allows `tla modules build` and `tla tlc` to resolve your Java overrides regardless of where the commands are executed.
|
|
196
|
+
> Setting a persistent `module_path` (and optionally `module_lib_path`) allows `tla modules build` and `tla tlc` to resolve your Java overrides regardless of where the commands are executed.
|
|
180
197
|
|
|
181
198
|
Verbose output:
|
|
182
199
|
```bash
|
|
@@ -211,7 +228,15 @@ On first run, a default config is created at:
|
|
|
211
228
|
~/.config/tla/config.yaml
|
|
212
229
|
```
|
|
213
230
|
|
|
214
|
-
|
|
231
|
+
You can manage the configuration using the `tla config` command:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
tla config list # Display current configuration
|
|
235
|
+
tla config edit # Open config in default editor ($EDITOR or vim)
|
|
236
|
+
tla config edit nano # Open config in a specific editor
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Example configuration (`config.yaml`):
|
|
215
240
|
|
|
216
241
|
```yaml
|
|
217
242
|
tla:
|
|
@@ -230,6 +255,7 @@ tlc:
|
|
|
230
255
|
overrides_class: tlc2.overrides.TLCOverrides
|
|
231
256
|
|
|
232
257
|
module_path: null # (Optional) Persistent custom modules path
|
|
258
|
+
module_lib_path: null # (Optional) Persistent custom modules lib path
|
|
233
259
|
|
|
234
260
|
java:
|
|
235
261
|
min_version: 11
|
|
@@ -146,8 +146,25 @@ Configure a persistent custom modules path:
|
|
|
146
146
|
tla modules path /path/to/custom/modules
|
|
147
147
|
```
|
|
148
148
|
|
|
149
|
+
View or reset the custom modules path:
|
|
150
|
+
```bash
|
|
151
|
+
tla modules path # View current path
|
|
152
|
+
tla modules path none # Reset to default
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Configure a persistent custom modules dependencies (lib) path:
|
|
156
|
+
```bash
|
|
157
|
+
tla modules lib /path/to/custom/libs
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
View or reset the custom lib path:
|
|
161
|
+
```bash
|
|
162
|
+
tla modules lib # View current path
|
|
163
|
+
tla modules lib none # Reset to default
|
|
164
|
+
```
|
|
165
|
+
|
|
149
166
|
> [!TIP]
|
|
150
|
-
> Setting a persistent `module_path` allows `tla modules build` and `tla tlc` to resolve your Java overrides regardless of where the commands are executed.
|
|
167
|
+
> Setting a persistent `module_path` (and optionally `module_lib_path`) allows `tla modules build` and `tla tlc` to resolve your Java overrides regardless of where the commands are executed.
|
|
151
168
|
|
|
152
169
|
Verbose output:
|
|
153
170
|
```bash
|
|
@@ -182,7 +199,15 @@ On first run, a default config is created at:
|
|
|
182
199
|
~/.config/tla/config.yaml
|
|
183
200
|
```
|
|
184
201
|
|
|
185
|
-
|
|
202
|
+
You can manage the configuration using the `tla config` command:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
tla config list # Display current configuration
|
|
206
|
+
tla config edit # Open config in default editor ($EDITOR or vim)
|
|
207
|
+
tla config edit nano # Open config in a specific editor
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Example configuration (`config.yaml`):
|
|
186
211
|
|
|
187
212
|
```yaml
|
|
188
213
|
tla:
|
|
@@ -201,6 +226,7 @@ tlc:
|
|
|
201
226
|
overrides_class: tlc2.overrides.TLCOverrides
|
|
202
227
|
|
|
203
228
|
module_path: null # (Optional) Persistent custom modules path
|
|
229
|
+
module_lib_path: null # (Optional) Persistent custom modules lib path
|
|
204
230
|
|
|
205
231
|
java:
|
|
206
232
|
min_version: 11
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tlaplus-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.2"
|
|
8
8
|
description = "TLA+ tools: download TLC, compile custom modules, run model checker"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -62,6 +62,7 @@ dev = [
|
|
|
62
62
|
"pre-commit>=3.5.0,<4.0.0",
|
|
63
63
|
"pre-commit-hooks>=6.0.0,<7.0.0",
|
|
64
64
|
"twine>=6.0.0,<7.0.0",
|
|
65
|
+
"bandit>=1.9.4",
|
|
65
66
|
]
|
|
66
67
|
|
|
67
68
|
[tool.pytest.ini_options]
|
|
@@ -105,10 +106,14 @@ ignore = [
|
|
|
105
106
|
"PLR0913", # Many arguments are common in tests (fixtures)
|
|
106
107
|
]
|
|
107
108
|
|
|
109
|
+
[tool.bandit]
|
|
110
|
+
skips = ["B404", "B603", "B607"]
|
|
111
|
+
|
|
108
112
|
[tool.poe.tasks]
|
|
109
113
|
check = "pre-commit run --all-files"
|
|
110
|
-
lint = ["lint-ruff", "type-check"]
|
|
114
|
+
lint = ["lint-ruff", "lint-bandit", "type-check"]
|
|
111
115
|
lint-ruff = "ruff check ."
|
|
116
|
+
lint-bandit = "bandit -c pyproject.toml -r src/tlaplus_cli"
|
|
112
117
|
type-check = "mypy ."
|
|
113
118
|
fix = ["format", "lint-fix"]
|
|
114
119
|
format = "ruff format ."
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from dataclasses import asdict
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from tlaplus_cli.ui import warn
|
|
6
|
+
from tlaplus_cli.versioning.schema import RemoteVersion
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def load_github_cache(cache_file: Path) -> list[RemoteVersion] | None:
|
|
10
|
+
"""Load the remote versions cache from disk."""
|
|
11
|
+
if cache_file.exists():
|
|
12
|
+
try:
|
|
13
|
+
with cache_file.open("r", encoding="utf-8") as f:
|
|
14
|
+
data = json.load(f)
|
|
15
|
+
return [RemoteVersion(**item) for item in data]
|
|
16
|
+
except (json.JSONDecodeError, OSError, KeyError, TypeError) as e:
|
|
17
|
+
warn(f"Failed to read cache: {e}")
|
|
18
|
+
return None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def save_github_cache(cache_file: Path, versions: list[RemoteVersion]) -> None:
|
|
22
|
+
"""Save the remote versions cache to disk."""
|
|
23
|
+
try:
|
|
24
|
+
cache_file.parent.mkdir(parents=True, exist_ok=True)
|
|
25
|
+
with cache_file.open("w", encoding="utf-8") as f:
|
|
26
|
+
json.dump([asdict(v) for v in versions], f)
|
|
27
|
+
except OSError as e:
|
|
28
|
+
warn(f"Failed to save cache: {e}")
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""TLA+ CLI tool - entry point."""
|
|
2
|
+
|
|
3
|
+
import importlib.metadata
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from tlaplus_cli.cmd.check_java import check_java
|
|
8
|
+
from tlaplus_cli.cmd.config import app as config_app
|
|
9
|
+
from tlaplus_cli.cmd.fetch_cache import app as fetch_cache_app
|
|
10
|
+
from tlaplus_cli.cmd.modules import app as modules_app
|
|
11
|
+
from tlaplus_cli.cmd.tlc import tlc as run_tlc_cmd
|
|
12
|
+
from tlaplus_cli.cmd.tools import app as tools_app
|
|
13
|
+
from tlaplus_cli.config.loader import load_config
|
|
14
|
+
|
|
15
|
+
app = typer.Typer(
|
|
16
|
+
name="tla",
|
|
17
|
+
help="TLA+ tools: download TLA+ toolset distribution, compile custom modules, run model checker.",
|
|
18
|
+
no_args_is_help=True,
|
|
19
|
+
add_completion=False,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def version_callback(value: bool) -> None:
|
|
24
|
+
if value:
|
|
25
|
+
meta = importlib.metadata.metadata("tlaplus-cli")
|
|
26
|
+
typer.echo(f"{meta['Name']} v{meta['Version']}")
|
|
27
|
+
typer.echo(meta["Summary"])
|
|
28
|
+
raise typer.Exit()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@app.callback()
|
|
32
|
+
def root(
|
|
33
|
+
version: bool = typer.Option( # noqa: ARG001
|
|
34
|
+
None,
|
|
35
|
+
"--version",
|
|
36
|
+
"-v",
|
|
37
|
+
help="Show the application's version and exit.",
|
|
38
|
+
callback=version_callback,
|
|
39
|
+
is_eager=True,
|
|
40
|
+
),
|
|
41
|
+
) -> None:
|
|
42
|
+
"""TLA+ CLI tool."""
|
|
43
|
+
# Load config early to trigger first-run copy
|
|
44
|
+
load_config()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# --- Subcommands ---
|
|
48
|
+
|
|
49
|
+
app.add_typer(modules_app, name="modules")
|
|
50
|
+
app.add_typer(tools_app, name="tools")
|
|
51
|
+
app.add_typer(fetch_cache_app, name="fetch-cache")
|
|
52
|
+
app.add_typer(config_app, name="config")
|
|
53
|
+
|
|
54
|
+
app.command(name="tlc")(run_tlc_cmd)
|
|
55
|
+
app.command(name="check-java")(check_java)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def main() -> None:
|
|
59
|
+
"""Entry point for [project.scripts]."""
|
|
60
|
+
app()
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
|
|
3
|
+
from tlaplus_cli.config.loader import load_config
|
|
4
|
+
from tlaplus_cli.java import get_java_version, validate_java_version
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def check_java() -> None:
|
|
8
|
+
"""Check if Java is installed and meets the minimum version requirement."""
|
|
9
|
+
config = load_config()
|
|
10
|
+
version = get_java_version()
|
|
11
|
+
if version:
|
|
12
|
+
typer.echo(f"Detected Java version: {version}")
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
validate_java_version(config.java.min_version)
|
|
16
|
+
typer.echo(f"Java version is compatible (>= {config.java.min_version}).")
|
|
17
|
+
except RuntimeError as e:
|
|
18
|
+
typer.echo(f"Error: {e}", err=True)
|
|
19
|
+
raise typer.Exit(1) from None
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import subprocess
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from tlaplus_cli.cmd.config import app
|
|
8
|
+
from tlaplus_cli.config.loader import config_path, load_config
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@app.command(name="edit")
|
|
12
|
+
def edit_config(
|
|
13
|
+
editor: str | None = typer.Argument(None, help="The editor to use (defaults to $EDITOR or 'vim')."),
|
|
14
|
+
) -> None:
|
|
15
|
+
"""Open the configuration file in an editor."""
|
|
16
|
+
cp = config_path()
|
|
17
|
+
|
|
18
|
+
# Ensure config exists by loading it
|
|
19
|
+
load_config()
|
|
20
|
+
|
|
21
|
+
if not editor:
|
|
22
|
+
editor = os.environ.get("EDITOR", "vim")
|
|
23
|
+
|
|
24
|
+
editor_path = shutil.which(editor)
|
|
25
|
+
if not editor_path:
|
|
26
|
+
typer.echo(f"Error: Editor '{editor}' not found in PATH.", err=True)
|
|
27
|
+
raise typer.Exit(1)
|
|
28
|
+
|
|
29
|
+
typer.echo(f"Opening {cp} with {editor} ...")
|
|
30
|
+
try:
|
|
31
|
+
subprocess.run([editor_path, str(cp)], check=True)
|
|
32
|
+
except subprocess.CalledProcessError as e:
|
|
33
|
+
typer.echo(f"Editor exited with error: {e}", err=True)
|
|
34
|
+
raise typer.Exit(1) from None
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
|
|
3
|
+
from tlaplus_cli.cmd.config import app
|
|
4
|
+
from tlaplus_cli.config.loader import config_path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@app.command(name="list")
|
|
8
|
+
def list_config() -> None:
|
|
9
|
+
"""Display the current configuration file content."""
|
|
10
|
+
cp = config_path()
|
|
11
|
+
if not cp.exists():
|
|
12
|
+
typer.echo("Configuration file not found.", err=True)
|
|
13
|
+
raise typer.Exit(1)
|
|
14
|
+
|
|
15
|
+
with cp.open(encoding="utf-8") as f:
|
|
16
|
+
typer.echo(f.read())
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
|
|
3
|
+
from tlaplus_cli.cmd.fetch_cache import app
|
|
4
|
+
from tlaplus_cli.versioning import clear_cache
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@app.command(name="clear")
|
|
8
|
+
def cmd_clear_cache() -> None:
|
|
9
|
+
"""Clear the local cache of remote GitHub versions."""
|
|
10
|
+
clear_cache()
|
|
11
|
+
typer.echo("GitHub versions cache cleared.")
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import typer
|
|
5
|
+
|
|
6
|
+
from tlaplus_cli.cmd.modules import app
|
|
7
|
+
from tlaplus_cli.tlc.compiler import compile_modules
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@app.command(name="build")
|
|
11
|
+
def build(
|
|
12
|
+
path: str | None = typer.Argument(None, help="Project root directory (defaults to workspace root)."),
|
|
13
|
+
verbose: bool = typer.Option(False, "--verbose", "-v", help="Show compilation output."),
|
|
14
|
+
) -> None:
|
|
15
|
+
"""Compile custom Java modules."""
|
|
16
|
+
base_dir = Path(path).resolve() if path is not None else None
|
|
17
|
+
|
|
18
|
+
typer.echo("Compiling Java files ...")
|
|
19
|
+
try:
|
|
20
|
+
classes_dir = compile_modules(base_dir, verbose)
|
|
21
|
+
except FileNotFoundError as e:
|
|
22
|
+
typer.echo(f"Error: {e}", err=True)
|
|
23
|
+
raise typer.Exit(1) from None
|
|
24
|
+
except subprocess.CalledProcessError:
|
|
25
|
+
typer.echo("Compilation failed!", err=True)
|
|
26
|
+
raise typer.Exit(1) from None
|
|
27
|
+
|
|
28
|
+
typer.echo(f"Successfully compiled to {classes_dir}")
|
|
29
|
+
service_file = classes_dir / "META-INF" / "services" / "tlc2.overrides.ITLCOverrides"
|
|
30
|
+
typer.echo(f"Created service file at {service_file}")
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
from tlaplus_cli.cmd.modules import app
|
|
6
|
+
from tlaplus_cli.config.loader import load_config, save_config, workspace_root
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@app.command(name="lib")
|
|
10
|
+
def set_modules_lib_path(
|
|
11
|
+
path: str | None = typer.Argument(
|
|
12
|
+
None, help="Path to the custom Java modules dependencies directory, or 'none' to reset."
|
|
13
|
+
),
|
|
14
|
+
) -> None:
|
|
15
|
+
"""Configure or view a persistent custom Java modules dependencies (lib) path."""
|
|
16
|
+
config_obj = load_config()
|
|
17
|
+
|
|
18
|
+
if path is None:
|
|
19
|
+
if config_obj.module_lib_path:
|
|
20
|
+
typer.echo(f"Current modules lib path: {config_obj.module_lib_path}")
|
|
21
|
+
else:
|
|
22
|
+
modules_dir = (
|
|
23
|
+
Path(config_obj.module_path)
|
|
24
|
+
if config_obj.module_path
|
|
25
|
+
else workspace_root() / config_obj.workspace.modules_dir
|
|
26
|
+
)
|
|
27
|
+
default_path = modules_dir / "lib"
|
|
28
|
+
typer.echo("Custom modules lib path is not set.")
|
|
29
|
+
typer.echo(f"Defaulting to: {default_path}")
|
|
30
|
+
return
|
|
31
|
+
|
|
32
|
+
if path.lower() == "none":
|
|
33
|
+
config_obj.module_lib_path = None
|
|
34
|
+
save_config(config_obj)
|
|
35
|
+
typer.echo("Custom modules lib path reset to default.")
|
|
36
|
+
return
|
|
37
|
+
|
|
38
|
+
p = Path(path).resolve()
|
|
39
|
+
|
|
40
|
+
if not p.is_dir():
|
|
41
|
+
typer.echo(f"Error: Path does not exist or is not a directory: {p}", err=True)
|
|
42
|
+
raise typer.Exit(1)
|
|
43
|
+
|
|
44
|
+
config_obj.module_lib_path = str(p)
|
|
45
|
+
save_config(config_obj)
|
|
46
|
+
typer.echo(f"Modules lib path updated to: {p}")
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
from tlaplus_cli.cmd.modules import app
|
|
6
|
+
from tlaplus_cli.config.loader import load_config, save_config, workspace_root
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@app.command(name="path")
|
|
10
|
+
def set_modules_path(
|
|
11
|
+
path: str | None = typer.Argument(None, help="Path to the custom Java modules directory, or 'none' to reset."),
|
|
12
|
+
) -> None:
|
|
13
|
+
"""Configure or view a persistent custom Java modules source path."""
|
|
14
|
+
config_obj = load_config()
|
|
15
|
+
|
|
16
|
+
if path is None:
|
|
17
|
+
if config_obj.module_path:
|
|
18
|
+
typer.echo(f"Current modules path: {config_obj.module_path}")
|
|
19
|
+
else:
|
|
20
|
+
default_path = workspace_root() / config_obj.workspace.modules_dir
|
|
21
|
+
typer.echo("Custom modules path is not set.")
|
|
22
|
+
typer.echo(f"Defaulting to: {default_path}")
|
|
23
|
+
return
|
|
24
|
+
|
|
25
|
+
if path.lower() == "none":
|
|
26
|
+
config_obj.module_path = None
|
|
27
|
+
save_config(config_obj)
|
|
28
|
+
typer.echo("Custom modules path reset to default.")
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
p = Path(path).resolve()
|
|
32
|
+
|
|
33
|
+
if not p.is_dir():
|
|
34
|
+
typer.echo(f"Error: Path does not exist or is not a directory: {p}", err=True)
|
|
35
|
+
raise typer.Exit(1)
|
|
36
|
+
|
|
37
|
+
config_obj.module_path = str(p)
|
|
38
|
+
save_config(config_obj)
|
|
39
|
+
typer.echo(f"Modules path updated to: {p}")
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
|
|
3
|
+
from tlaplus_cli.tlc.compiler import get_tlc_jar_path
|
|
4
|
+
from tlaplus_cli.tlc.runner import get_tlc_version, resolve_spec_file, run_tlc
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def version_callback(value: bool) -> None:
|
|
8
|
+
if value:
|
|
9
|
+
jar_path = get_tlc_jar_path()
|
|
10
|
+
typer.echo(f"tla2tools.jar path: {jar_path}")
|
|
11
|
+
|
|
12
|
+
if not jar_path.exists():
|
|
13
|
+
typer.echo(f"Error: tla2tools.jar not found at {jar_path}", err=True)
|
|
14
|
+
typer.echo("Run 'tla tools install' first.", err=True)
|
|
15
|
+
raise typer.Exit(1)
|
|
16
|
+
|
|
17
|
+
version_str = get_tlc_version()
|
|
18
|
+
if version_str:
|
|
19
|
+
typer.echo(version_str)
|
|
20
|
+
|
|
21
|
+
raise typer.Exit(0)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def tlc(
|
|
25
|
+
spec: str = typer.Argument(help="Name of the TLA+ specification (without .tla extension)."),
|
|
26
|
+
version: bool | None = typer.Option(
|
|
27
|
+
None,
|
|
28
|
+
"--version",
|
|
29
|
+
help="Print the path to tla2tools.jar and its version.",
|
|
30
|
+
callback=version_callback,
|
|
31
|
+
is_eager=True,
|
|
32
|
+
),
|
|
33
|
+
) -> None:
|
|
34
|
+
"""Run TLC model checker on a TLA+ specification."""
|
|
35
|
+
if version:
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
_, spec_name = resolve_spec_file(spec)
|
|
40
|
+
except FileNotFoundError as e:
|
|
41
|
+
typer.echo(f"Error: {e}", err=True)
|
|
42
|
+
raise typer.Exit(1) from None
|
|
43
|
+
|
|
44
|
+
typer.echo(f"Running TLC on {spec_name} ...")
|
|
45
|
+
try:
|
|
46
|
+
exit_code = run_tlc(spec)
|
|
47
|
+
except FileNotFoundError as e:
|
|
48
|
+
typer.echo(f"Error: {e}", err=True)
|
|
49
|
+
raise typer.Exit(1) from None
|
|
50
|
+
|
|
51
|
+
raise typer.Exit(exit_code)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
|
|
3
|
+
from tlaplus_cli.cmd.tools.meta import app as meta_app
|
|
4
|
+
|
|
5
|
+
app = typer.Typer(name="tools", help="Manage TLC tools (tla2tools.jar).", no_args_is_help=True)
|
|
6
|
+
app.add_typer(meta_app, name="meta")
|
|
7
|
+
|
|
8
|
+
from . import dir, install, list, path, pin, uninstall, upgrade # noqa: F401, E402
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
|
|
3
|
+
from tlaplus_cli.cmd.tools import app
|
|
4
|
+
from tlaplus_cli.versioning import get_tools_dir
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@app.command(name="dir")
|
|
8
|
+
def show_dir() -> None:
|
|
9
|
+
"""Show the absolute path to the local TLC tools cache directory."""
|
|
10
|
+
tools_dir = get_tools_dir()
|
|
11
|
+
typer.echo(str(tools_dir))
|
|
12
|
+
|
|
13
|
+
if tools_dir.is_dir():
|
|
14
|
+
versions = sorted([d.name for d in tools_dir.iterdir() if d.is_dir()])
|
|
15
|
+
for v in versions:
|
|
16
|
+
typer.echo(f" {v}")
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import requests
|
|
4
|
+
import typer
|
|
5
|
+
|
|
6
|
+
from tlaplus_cli.cmd.tools import app
|
|
7
|
+
from tlaplus_cli.config.loader import load_config
|
|
8
|
+
from tlaplus_cli.versioning import (
|
|
9
|
+
download_version,
|
|
10
|
+
download_version_from_url,
|
|
11
|
+
fetch_remote_versions,
|
|
12
|
+
get_pinned_version_dir,
|
|
13
|
+
get_tools_dir,
|
|
14
|
+
is_url,
|
|
15
|
+
set_pin,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _auto_pin_if_needed(version_dir: Path) -> None:
|
|
20
|
+
"""Pin the version if no version is currently pinned."""
|
|
21
|
+
pinned_dir = get_pinned_version_dir()
|
|
22
|
+
if pinned_dir is None:
|
|
23
|
+
typer.echo(f"Auto-pinning newly installed version {version_dir.name}")
|
|
24
|
+
set_pin(version_dir)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@app.command()
|
|
28
|
+
def install(
|
|
29
|
+
version: str = typer.Argument(None, help="Version tag (e.g. 'v1.8.0') or a direct URL to tla2tools.jar."),
|
|
30
|
+
force: bool = typer.Option(False, "--force", "-f", help="Re-download if already installed."),
|
|
31
|
+
) -> None:
|
|
32
|
+
"""Download and install a specific TLC version."""
|
|
33
|
+
if version and is_url(version):
|
|
34
|
+
try:
|
|
35
|
+
version_dir = download_version_from_url(version)
|
|
36
|
+
except (requests.RequestException, OSError, ValueError) as e:
|
|
37
|
+
typer.echo(f"Error: Failed to download: {e}", err=True)
|
|
38
|
+
raise typer.Exit(1) from e
|
|
39
|
+
else:
|
|
40
|
+
typer.echo("Download complete.")
|
|
41
|
+
typer.echo(f"Successfully installed from URL to {version_dir}")
|
|
42
|
+
_auto_pin_if_needed(version_dir)
|
|
43
|
+
return
|
|
44
|
+
|
|
45
|
+
config = load_config()
|
|
46
|
+
versions, status = fetch_remote_versions(config.tla.urls.tags, config.tla.urls.releases, config.tla.urls.per_page)
|
|
47
|
+
|
|
48
|
+
if not versions:
|
|
49
|
+
typer.echo(f"Error: Could not fetch remote versions (status: {status.value})", err=True)
|
|
50
|
+
raise typer.Exit(1)
|
|
51
|
+
|
|
52
|
+
target = None
|
|
53
|
+
if version:
|
|
54
|
+
target = next((v for v in versions if v.name == version), None)
|
|
55
|
+
if not target:
|
|
56
|
+
typer.echo(f"Error: Version {version} not found.", err=True)
|
|
57
|
+
raise typer.Exit(1)
|
|
58
|
+
else:
|
|
59
|
+
typer.echo("No version specified, selecting latest stable release.")
|
|
60
|
+
# Default to latest non-prerelease
|
|
61
|
+
target = next((v for v in versions if not v.prerelease), versions[0])
|
|
62
|
+
|
|
63
|
+
# Check if already installed
|
|
64
|
+
target_dir = get_tools_dir() / f"{target.name}-{target.short_sha}"
|
|
65
|
+
if target_dir.exists() and not force:
|
|
66
|
+
typer.echo(f"Version {target.name} is already installed.")
|
|
67
|
+
typer.echo(f"Successfully installed {target.name} to {target_dir}")
|
|
68
|
+
_auto_pin_if_needed(target_dir)
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
version_dir = download_version(target, force=force)
|
|
73
|
+
typer.echo("Download complete.")
|
|
74
|
+
typer.echo(f"Successfully installed {target.name} to {version_dir}")
|
|
75
|
+
except (requests.RequestException, OSError) as e:
|
|
76
|
+
typer.echo(f"Error: Failed to download: {e}", err=True)
|
|
77
|
+
raise typer.Exit(1) from e
|
|
78
|
+
|
|
79
|
+
_auto_pin_if_needed(version_dir)
|