fm-weck 1.0.0__py3-none-any.whl → 1.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 +79 -82
- {fm_weck-1.0.0.dist-info → fm_weck-1.1.1.dist-info}/METADATA +13 -10
- {fm_weck-1.0.0.dist-info → fm_weck-1.1.1.dist-info}/RECORD +6 -6
- {fm_weck-1.0.0.dist-info → fm_weck-1.1.1.dist-info}/WHEEL +0 -0
- {fm_weck-1.0.0.dist-info → fm_weck-1.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
|
-
|
|
105
|
-
return parser, run, subparsers
|
|
106
102
|
|
|
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,45 @@ 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
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
args = normal_parser.parse_args(raw_args)
|
|
203
|
-
except argparse.ArgumentError:
|
|
204
|
-
# Either: Parse faulty args again to display nice help message
|
|
205
|
-
# Or: shell was called: proceed normally
|
|
206
|
-
args = normal_parser.parse_args(raw_args)
|
|
177
|
+
result, left_over = parser.parse_known_args(raw_args)
|
|
178
|
+
|
|
179
|
+
if not left_over:
|
|
180
|
+
# Parsing went fine
|
|
181
|
+
return help_callback, result
|
|
182
|
+
|
|
183
|
+
# Find the first offending argument and insert "--" before it
|
|
184
|
+
# We do this to allow the user to pass arguments to the fm-tool without
|
|
185
|
+
# having to specify the pseudo argument "--"
|
|
186
|
+
idx = raw_args.index(left_over[0])
|
|
187
|
+
raw_args.insert(idx, "--")
|
|
207
188
|
|
|
208
|
-
return help_callback,
|
|
189
|
+
return help_callback, parser.parse_args(raw_args)
|
|
209
190
|
|
|
210
191
|
|
|
211
192
|
@cache
|
|
@@ -300,6 +281,21 @@ def main_manual(args: argparse.Namespace):
|
|
|
300
281
|
)
|
|
301
282
|
|
|
302
283
|
|
|
284
|
+
def main_install(args: argparse.Namespace):
|
|
285
|
+
for tool in args.TOOL:
|
|
286
|
+
try:
|
|
287
|
+
fm_data = resolve_tool(tool)
|
|
288
|
+
except KeyError:
|
|
289
|
+
logging.error("Unknown tool %s. Skipping installation...", tool)
|
|
290
|
+
continue
|
|
291
|
+
|
|
292
|
+
setup_fm_tool(
|
|
293
|
+
fm_tool=fm_data,
|
|
294
|
+
version=tool.version,
|
|
295
|
+
configuration=Config(),
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
|
|
303
299
|
def main_shell(args: argparse.Namespace):
|
|
304
300
|
if not args.TOOL:
|
|
305
301
|
engine = Engine.from_config(Config())
|
|
@@ -315,14 +311,13 @@ def main_shell(args: argparse.Namespace):
|
|
|
315
311
|
|
|
316
312
|
|
|
317
313
|
def log_no_image_error(tool, config):
|
|
318
|
-
|
|
319
314
|
order = []
|
|
320
315
|
for path in _SEARCH_ORDER:
|
|
321
316
|
if path.is_relative_to(Path.cwd()):
|
|
322
317
|
order.append(str(path.relative_to(Path.cwd())))
|
|
323
318
|
else:
|
|
324
319
|
order.append(str(path))
|
|
325
|
-
|
|
320
|
+
|
|
326
321
|
text = ""
|
|
327
322
|
if tool:
|
|
328
323
|
text = f"{os.linesep}No image specified in the fm-tool yml file for {tool.tool}."
|
|
@@ -372,6 +367,8 @@ def cli(raw_args: list[str]):
|
|
|
372
367
|
print(f" - {prop}")
|
|
373
368
|
return
|
|
374
369
|
|
|
370
|
+
print(args)
|
|
371
|
+
|
|
375
372
|
if not hasattr(args, "TOOL"):
|
|
376
373
|
return help_callback()
|
|
377
374
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: fm-weck
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.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=JmvX_jGKmQ09GVpuyVB9ZmJNcje4Z656BtYxqN5hONk,351
|
|
2
2
|
fm_weck/__main__.py,sha256=E7z4-9t6To3hbIPjRPu6iW17YCrtqpDSbFSpd9pX4NA,350
|
|
3
|
-
fm_weck/cli.py,sha256=
|
|
3
|
+
fm_weck/cli.py,sha256=apqfvp0zqcFKTH0RSKglkxvSd3d9nOmnpsh6E6-3J8I,10499
|
|
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-1.
|
|
127
|
-
fm_weck-1.
|
|
128
|
-
fm_weck-1.
|
|
129
|
-
fm_weck-1.
|
|
126
|
+
fm_weck-1.1.1.dist-info/METADATA,sha256=0whpQXhGwHbVo4N4MpeqbfZ_F2JtzFAYb2cad3-GrjM,2744
|
|
127
|
+
fm_weck-1.1.1.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
128
|
+
fm_weck-1.1.1.dist-info/entry_points.txt,sha256=toWpKCSY1u593MPnI_xW5gnwlnkerP4AvmPQ1s2nPgY,50
|
|
129
|
+
fm_weck-1.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|