fm-weck 0.2.1__py3-none-any.whl → 1.1__py3-none-any.whl
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.
- fm_weck/__init__.py +1 -1
- fm_weck/cli.py +81 -81
- {fm_weck-0.2.1.dist-info → fm_weck-1.1.dist-info}/METADATA +13 -10
- {fm_weck-0.2.1.dist-info → fm_weck-1.1.dist-info}/RECORD +6 -6
- {fm_weck-0.2.1.dist-info → fm_weck-1.1.dist-info}/WHEEL +1 -1
- {fm_weck-0.2.1.dist-info → fm_weck-1.1.dist-info}/entry_points.txt +0 -0
fm_weck/__init__.py
CHANGED
fm_weck/cli.py
CHANGED
|
@@ -12,7 +12,7 @@ from argparse import Namespace
|
|
|
12
12
|
from dataclasses import dataclass
|
|
13
13
|
from functools import cache
|
|
14
14
|
from pathlib import Path
|
|
15
|
-
from typing import Any, Callable, Optional, Tuple, Union
|
|
15
|
+
from typing import Any, Callable, Optional, Tuple, Union
|
|
16
16
|
|
|
17
17
|
from fm_tools.benchexec_helper import DataModel
|
|
18
18
|
|
|
@@ -22,7 +22,7 @@ from fm_weck.resources import iter_fm_data, iter_properties
|
|
|
22
22
|
|
|
23
23
|
from . import __version__
|
|
24
24
|
from .engine import Engine, NoImageError
|
|
25
|
-
from .serve import run_guided, run_manual
|
|
25
|
+
from .serve import run_guided, run_manual, setup_fm_tool
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
@dataclass
|
|
@@ -45,9 +45,30 @@ class ToolQualifier:
|
|
|
45
45
|
return
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
def
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
def add_tool_arg(parser, nargs="?"):
|
|
49
|
+
parser.add_argument(
|
|
50
|
+
"TOOL",
|
|
51
|
+
help="The tool to obtain the container from. Can be the form <tool>:<version>. "
|
|
52
|
+
"The TOOL is either the name of a bundled tool (c.f. fm-weck --list) or "
|
|
53
|
+
"the path to a fm-tools yaml file.",
|
|
54
|
+
type=ToolQualifier,
|
|
55
|
+
nargs=nargs,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def add_shared_args_for_run_modes(parser):
|
|
60
|
+
parser.add_argument(
|
|
61
|
+
"--skip-download",
|
|
62
|
+
action="store_true",
|
|
63
|
+
help="Do not download the fm-tool, even if it is not available in the cache.",
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
add_tool_arg(parser, nargs=None)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def parse(raw_args: list[str]) -> Tuple[Callable[[], None], Namespace]:
|
|
70
|
+
parser = argparse.ArgumentParser(description="fm-weck")
|
|
71
|
+
|
|
51
72
|
parser.add_argument(
|
|
52
73
|
"--version",
|
|
53
74
|
action="version",
|
|
@@ -78,55 +99,8 @@ def add_shared_arguments(
|
|
|
78
99
|
)
|
|
79
100
|
|
|
80
101
|
subparsers = parser.add_subparsers()
|
|
81
|
-
run = subparsers.add_parser("run", help="Run a verifier inside a container.")
|
|
82
|
-
|
|
83
|
-
run.add_argument(
|
|
84
|
-
"-m",
|
|
85
|
-
"--manual",
|
|
86
|
-
action="store_true",
|
|
87
|
-
required=require_manual,
|
|
88
|
-
help="Enable manual mode. All args past <tool>:<version> are passed verbatim to the tool.",
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
run.add_argument(
|
|
92
|
-
"--skip-download",
|
|
93
|
-
action="store_true",
|
|
94
|
-
help="Do not download the fm-tool, even if it is not available in the cache.",
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
run.add_argument(
|
|
98
|
-
"TOOL",
|
|
99
|
-
help="The tool to use. Can be the form <tool>:<version>. "
|
|
100
|
-
"The TOOL is either the name of a bundled tool (c.f. fm-weck --list) or "
|
|
101
|
-
"the path to a fm-tools yaml file.",
|
|
102
|
-
type=ToolQualifier,
|
|
103
|
-
)
|
|
104
102
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
class MayFailParserError(Exception):
|
|
109
|
-
pass
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
class MayFailParser(argparse.ArgumentParser):
|
|
113
|
-
def error(self, message):
|
|
114
|
-
raise MayFailParserError
|
|
115
|
-
|
|
116
|
-
def format_help(self):
|
|
117
|
-
raise MayFailParserError
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
def parse(raw_args: list[str]) -> tuple[Callable[[], None], Namespace]:
|
|
121
|
-
manual_parser = MayFailParser(description="fm-weck", exit_on_error=False)
|
|
122
|
-
normal_parser = argparse.ArgumentParser(description="fm-weck")
|
|
123
|
-
|
|
124
|
-
manual_parser, run, _ = add_shared_arguments(manual_parser, require_manual=True)
|
|
125
|
-
# manual mode
|
|
126
|
-
run.add_argument("argument_list", metavar="args", nargs="*", help="Arguments for the fm-tool")
|
|
127
|
-
run.set_defaults(main=main_manual)
|
|
128
|
-
|
|
129
|
-
normal_parser, run, subparsers = add_shared_arguments(normal_parser)
|
|
103
|
+
run = subparsers.add_parser("run", aliases=["r"], help="Run a verifier inside a container.")
|
|
130
104
|
|
|
131
105
|
# guided mode
|
|
132
106
|
run.add_argument(
|
|
@@ -163,6 +137,8 @@ def parse(raw_args: list[str]) -> tuple[Callable[[], None], Namespace]:
|
|
|
163
137
|
default=None,
|
|
164
138
|
)
|
|
165
139
|
|
|
140
|
+
add_shared_args_for_run_modes(run)
|
|
141
|
+
|
|
166
142
|
run.add_argument("files", metavar="FILES", nargs="+", help="Files to pass to the tool")
|
|
167
143
|
run.add_argument(
|
|
168
144
|
"argument_list",
|
|
@@ -172,40 +148,48 @@ def parse(raw_args: list[str]) -> tuple[Callable[[], None], Namespace]:
|
|
|
172
148
|
)
|
|
173
149
|
run.set_defaults(main=main_run)
|
|
174
150
|
|
|
151
|
+
expert = subparsers.add_parser(
|
|
152
|
+
"expert",
|
|
153
|
+
aliases=["e", "m"],
|
|
154
|
+
help="Manually run a verifier inside a container."
|
|
155
|
+
"Arguments are passed verbatim to the tool, so expert-ise about it's command line is required.",
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
add_shared_args_for_run_modes(expert)
|
|
159
|
+
|
|
160
|
+
expert.add_argument("argument_list", metavar="args", nargs="*", help="Arguments for the fm-tool")
|
|
161
|
+
expert.set_defaults(main=main_manual)
|
|
162
|
+
|
|
175
163
|
shell = subparsers.add_parser("shell", help="Start an interactive shell inside the container.")
|
|
176
|
-
|
|
164
|
+
|
|
177
165
|
shell.add_argument("--entry", action="store", help="The entry point of the shell.", default="/bin/bash")
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
help="The tool to obtain the container from. Can be the form <tool>:<version>. "
|
|
181
|
-
"The TOOL is either the name of a bundled tool (c.f. fm-weck --list) or "
|
|
182
|
-
"the path to a fm-tools yaml file.",
|
|
183
|
-
type=ToolQualifier,
|
|
184
|
-
nargs="?",
|
|
185
|
-
)
|
|
166
|
+
|
|
167
|
+
add_tool_arg(shell)
|
|
186
168
|
shell.set_defaults(main=main_shell)
|
|
187
169
|
|
|
170
|
+
install = subparsers.add_parser("install", aliases=["i"], help="Download and unpack a TOOL for later use.")
|
|
171
|
+
add_tool_arg(install, nargs="+")
|
|
172
|
+
install.set_defaults(main=main_install)
|
|
173
|
+
|
|
188
174
|
def help_callback():
|
|
189
|
-
|
|
175
|
+
parser.print_help()
|
|
190
176
|
|
|
191
177
|
try:
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
#
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
# Or: shell was called: proceed normally
|
|
206
|
-
args = normal_parser.parse_args(raw_args)
|
|
178
|
+
parser.parse_args(raw_args)
|
|
179
|
+
except SystemExit as e:
|
|
180
|
+
_, left_over = parser.parse_known_args(raw_args)
|
|
181
|
+
|
|
182
|
+
if not left_over:
|
|
183
|
+
# Some unrecoverable error occurred
|
|
184
|
+
raise e
|
|
185
|
+
|
|
186
|
+
# Find the first offending argument and insert "--" before it
|
|
187
|
+
# We do this to allow the user to pass arguments to the fm-tool without
|
|
188
|
+
# having to specify the pseudo argument "--"
|
|
189
|
+
idx = raw_args.index(left_over[0])
|
|
190
|
+
raw_args.insert(idx, "--")
|
|
207
191
|
|
|
208
|
-
return help_callback,
|
|
192
|
+
return help_callback, parser.parse_args(raw_args)
|
|
209
193
|
|
|
210
194
|
|
|
211
195
|
@cache
|
|
@@ -300,6 +284,21 @@ def main_manual(args: argparse.Namespace):
|
|
|
300
284
|
)
|
|
301
285
|
|
|
302
286
|
|
|
287
|
+
def main_install(args: argparse.Namespace):
|
|
288
|
+
for tool in args.TOOL:
|
|
289
|
+
try:
|
|
290
|
+
fm_data = resolve_tool(tool)
|
|
291
|
+
except KeyError:
|
|
292
|
+
logging.error("Unknown tool %s. Skipping installation...", tool)
|
|
293
|
+
continue
|
|
294
|
+
|
|
295
|
+
setup_fm_tool(
|
|
296
|
+
fm_tool=fm_data,
|
|
297
|
+
version=tool.version,
|
|
298
|
+
configuration=Config(),
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
|
|
303
302
|
def main_shell(args: argparse.Namespace):
|
|
304
303
|
if not args.TOOL:
|
|
305
304
|
engine = Engine.from_config(Config())
|
|
@@ -315,14 +314,13 @@ def main_shell(args: argparse.Namespace):
|
|
|
315
314
|
|
|
316
315
|
|
|
317
316
|
def log_no_image_error(tool, config):
|
|
318
|
-
|
|
319
317
|
order = []
|
|
320
318
|
for path in _SEARCH_ORDER:
|
|
321
319
|
if path.is_relative_to(Path.cwd()):
|
|
322
320
|
order.append(str(path.relative_to(Path.cwd())))
|
|
323
321
|
else:
|
|
324
322
|
order.append(str(path))
|
|
325
|
-
|
|
323
|
+
|
|
326
324
|
text = ""
|
|
327
325
|
if tool:
|
|
328
326
|
text = f"{os.linesep}No image specified in the fm-tool yml file for {tool.tool}."
|
|
@@ -372,6 +370,8 @@ def cli(raw_args: list[str]):
|
|
|
372
370
|
print(f" - {prop}")
|
|
373
371
|
return
|
|
374
372
|
|
|
373
|
+
print(args)
|
|
374
|
+
|
|
375
375
|
if not hasattr(args, "TOOL"):
|
|
376
376
|
return help_callback()
|
|
377
377
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: fm-weck
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1.1
|
|
4
4
|
Author-email: Henrik Wachowitz <henrik.wachowitz@ifi.lmu.de>
|
|
5
5
|
Maintainer-email: Henrik Wachowitz <henrik.wachowitz@ifi.lmu.de>
|
|
6
6
|
Classifier: Development Status :: 4 - Beta
|
|
@@ -24,9 +24,12 @@ SPDX-FileCopyrightText: 2024 Dirk Beyer <https://www.sosy-lab.org>
|
|
|
24
24
|
SPDX-License-Identifier: Apache-2.0
|
|
25
25
|
-->
|
|
26
26
|
|
|
27
|
-
# fm-weck
|
|
27
|
+
# fm-weck: Run formal methods tools in containerized environments
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
fm-weck is a command line tool and library that makes the execution of formal methods tools easy. fm-weck downloads the tools and caches them for later use.
|
|
30
|
+
|
|
31
|
+
<!-- To get an impression check out the corresponding [FM '24 Paper](https://www.sosy-lab.org/research/pub/2024/). -->
|
|
32
|
+
We provide a tutorial on how to use fm-weck [here](doc/Tutorial.md).
|
|
30
33
|
|
|
31
34
|
## Install dependencies
|
|
32
35
|
|
|
@@ -36,19 +39,19 @@ This project builds on Podman. To develop, you need to install Podman.
|
|
|
36
39
|
sudo apt install podman
|
|
37
40
|
```
|
|
38
41
|
|
|
39
|
-
##
|
|
42
|
+
## Modes of Operation
|
|
40
43
|
|
|
41
|
-
There are three modes of operation: `run`, `shell` and `
|
|
44
|
+
There are three modes of operation: `run`, `shell` and `expert`.
|
|
42
45
|
|
|
43
|
-
- `
|
|
44
|
-
corresponding fm-
|
|
45
|
-
- `shell`: enters an interactive shell inside of the container specified by the given
|
|
46
|
-
- `
|
|
46
|
+
- `expert`: executes a tool in it's containerized environment specified through the
|
|
47
|
+
corresponding fm-tools YAML file: All arguments are passed verbatim to the tool.
|
|
48
|
+
- `shell`: enters an interactive shell inside of the container specified by the given tool
|
|
49
|
+
- `run`: enables plug-and-play execution of formal methods tools: it
|
|
47
50
|
downloads and unpacks a tool from the fm-tools metadata file into a user-specified cache directory on the host system and then runs the tool in the containerized environment
|
|
48
51
|
|
|
49
52
|
## Development and Testing
|
|
50
53
|
|
|
51
|
-
When using any command with the `fm-weck toolname ...` syntax, the tool name is searched in `src/fm_weck/resources/fm_tools`.
|
|
54
|
+
When using any command with the `fm-weck <cmd> toolname ...` syntax, the tool name is searched in `src/fm_weck/resources/fm_tools`.
|
|
52
55
|
During the build process of the `.whl` file for `fm-weck`, the `fm_tools/data` directory is copied to that location.
|
|
53
56
|
When running or developing `fm-weck` from the git repository, the user must make sure that the contents of `fm_tools/data` directory are
|
|
54
57
|
available in the `src/fm_weck/resources/fm_tools` directory.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
fm_weck/__init__.py,sha256=
|
|
1
|
+
fm_weck/__init__.py,sha256=nN88NCpdZVISleeiEKZNzQIEqfhYGseFqAKRwEWWboo,349
|
|
2
2
|
fm_weck/__main__.py,sha256=E7z4-9t6To3hbIPjRPu6iW17YCrtqpDSbFSpd9pX4NA,350
|
|
3
|
-
fm_weck/cli.py,sha256=
|
|
3
|
+
fm_weck/cli.py,sha256=b0xU_GBs_7ETRzNfcFBSRfCarVT1Ix8sR0Q7LDLJ0S4,10598
|
|
4
4
|
fm_weck/config.py,sha256=E3TZbUv9za6XkuLTBGeuxUjLqYKW6IIz2i_N-N47DVI,3872
|
|
5
5
|
fm_weck/engine.py,sha256=TIeyCevSjB_PQ5DiYfi7xNjeIRh2CJ636EX5kAY3gKs,7507
|
|
6
6
|
fm_weck/image_mgr.py,sha256=1lddYSVd4-dILfhMjDo87S5wfW7qeefInJpyV0Jao_4,1375
|
|
@@ -123,7 +123,7 @@ fm_weck/resources/fm_tools/wasp-c.yml,sha256=NWEb2vpIBu75kZJdEq0am8Mpi2HFu5nhDI1
|
|
|
123
123
|
fm_weck/resources/fm_tools/wit4java.yml,sha256=SukwwE46DsDmZouAwHhr_aaOjxIaeOrIS7o7P4eDWX0,1243
|
|
124
124
|
fm_weck/resources/fm_tools/witch.yml,sha256=1NtUf5SlXtCTqJZHjENcjqZMMqnKGlb4awSUwBDEvWw,913
|
|
125
125
|
fm_weck/resources/fm_tools/witnesslint.yml,sha256=Y6A2TXPyjVxZ9Fhmyd7GOKY7x1_jXjshvmrIM4uW96A,3085
|
|
126
|
-
fm_weck-
|
|
127
|
-
fm_weck-
|
|
128
|
-
fm_weck-
|
|
129
|
-
fm_weck-
|
|
126
|
+
fm_weck-1.1.dist-info/METADATA,sha256=SRWhnPT1nNJfhZAYyv9XoI2OtRzSlUe2aNVV4P3wExY,2742
|
|
127
|
+
fm_weck-1.1.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
128
|
+
fm_weck-1.1.dist-info/entry_points.txt,sha256=toWpKCSY1u593MPnI_xW5gnwlnkerP4AvmPQ1s2nPgY,50
|
|
129
|
+
fm_weck-1.1.dist-info/RECORD,,
|
|
File without changes
|