fm-weck 1.3.0__py3-none-any.whl → 1.4.0__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 CHANGED
@@ -8,4 +8,4 @@
8
8
  from .config import Config # noqa: F401
9
9
  from .image_mgr import ImageMgr # noqa: F401
10
10
 
11
- __version__ = "1.3.0"
11
+ __version__ = "1.4.0"
fm_weck/cli.py CHANGED
@@ -14,15 +14,29 @@ from functools import cache
14
14
  from pathlib import Path
15
15
  from typing import Any, Callable, Optional, Tuple, Union
16
16
 
17
- from fm_tools.benchexec_helper import DataModel
17
+ try:
18
+ from fm_tools.benchexec_helper import DataModel
19
+ except ImportError:
20
+ from enum import Enum
21
+
22
+ class DataModel(Enum):
23
+ """
24
+ Enum representing the data model of the tool.
25
+ """
26
+
27
+ LP64 = "LP64"
28
+ ILP32 = "ILP32"
29
+
30
+ def __str__(self):
31
+ return self.value
32
+
18
33
 
19
34
  from fm_weck import Config
20
35
  from fm_weck.config import _SEARCH_ORDER
21
36
  from fm_weck.resources import iter_fm_data, iter_properties
22
37
 
23
38
  from . import __version__
24
- from .engine import Engine, NoImageError
25
- from .serve import run_guided, run_manual, run_runexec, setup_fm_tool
39
+ from .exceptions import NoImageError
26
40
 
27
41
  logger = logging.getLogger(__name__)
28
42
 
@@ -84,12 +98,22 @@ def parse(raw_args: list[str]) -> Tuple[Callable[[], None], Namespace]:
84
98
  default=None,
85
99
  )
86
100
 
101
+ loglevels_lower = ["debug", "info", "warning", "error", "critical"]
102
+ loglevels = loglevels_lower + [level.upper() for level in loglevels_lower]
87
103
  parser.add_argument(
88
104
  "--loglevel",
89
- choices=["debug", "info", "warning", "error", "critical"],
105
+ choices=loglevels,
106
+ metavar="LEVEL",
107
+ action="store",
108
+ default=None,
109
+ help="Set the log level. Valid values are: " + ", ".join(loglevels_lower),
110
+ )
111
+
112
+ parser.add_argument(
113
+ "--logfile",
90
114
  action="store",
115
+ help="Path to the log file.",
91
116
  default=None,
92
- help="Set the log level.",
93
117
  )
94
118
 
95
119
  parser.add_argument(
@@ -204,6 +228,16 @@ def parse(raw_args: list[str]) -> Tuple[Callable[[], None], Namespace]:
204
228
  default=None,
205
229
  )
206
230
 
231
+ # Arguments passed though to the container manager (i.e., docker or podman)
232
+ runexec.add_argument(
233
+ "--container-long-opt",
234
+ dest="container_long_opts",
235
+ help="Arguments passed as long options (prepending --) directly to the container manager "
236
+ "(e.g., docker or podman). Each usage passes additional arguments to the container manager.",
237
+ action="append",
238
+ nargs="+",
239
+ )
240
+
207
241
  runexec.add_argument("argument_list", metavar="args", nargs="*", help="Arguments for runexec.")
208
242
  runexec.set_defaults(main=main_runexec)
209
243
 
@@ -264,14 +298,19 @@ def resolve_property(prop_name: str) -> Path:
264
298
  return property_choice_map()[prop_name]
265
299
 
266
300
 
267
- def set_log_level(loglevel: Optional[str], config: dict[str, Any]):
301
+ def set_log_options(loglevel: Optional[str], logfile: Optional[str], config: dict[str, Any]):
268
302
  level = "WARNING"
269
303
  level = loglevel.upper() if loglevel else config.get("logging", {}).get("level", level)
270
- logging.basicConfig(level=level)
304
+ if logfile:
305
+ logging.basicConfig(level=level, filename=logfile)
306
+ else:
307
+ logging.basicConfig(level=level)
271
308
  logging.getLogger("httpcore").setLevel("WARNING")
272
309
 
273
310
 
274
311
  def main_run(args: argparse.Namespace):
312
+ from .serve import run_guided
313
+
275
314
  if not args.TOOL:
276
315
  logger.error("No fm-tool given. Aborting...")
277
316
  return 1
@@ -300,15 +339,20 @@ def main_run(args: argparse.Namespace):
300
339
 
301
340
 
302
341
  def main_runexec(args: argparse.Namespace):
342
+ from .runexec_mode import run_runexec
343
+
303
344
  run_runexec(
304
345
  benchexec_package=args.benchexec_package,
305
346
  use_image=args.use_image,
306
347
  configuration=Config(),
348
+ extra_container_args=args.container_long_opts or [],
307
349
  command=args.argument_list,
308
350
  )
309
351
 
310
352
 
311
353
  def main_manual(args: argparse.Namespace):
354
+ from .serve import run_manual
355
+
312
356
  if not args.TOOL:
313
357
  logger.error("No fm-tool given. Aborting...")
314
358
  return 1
@@ -328,6 +372,8 @@ def main_manual(args: argparse.Namespace):
328
372
 
329
373
 
330
374
  def main_install(args: argparse.Namespace):
375
+ from .serve import setup_fm_tool
376
+
331
377
  for tool in args.TOOL:
332
378
  try:
333
379
  fm_data = resolve_tool(tool)
@@ -343,6 +389,8 @@ def main_install(args: argparse.Namespace):
343
389
 
344
390
 
345
391
  def main_shell(args: argparse.Namespace):
392
+ from .engine import Engine
393
+
346
394
  if not args.TOOL:
347
395
  engine = Engine.from_config(Config())
348
396
  else:
@@ -378,7 +426,7 @@ Please specify an image in the fm-tool yml file or add a configuration.
378
426
 
379
427
  To add a configuration you can do the following (on POSIX Terminals):
380
428
 
381
- printf '[defaults]\\nimage = "<your_image>"' > .weck
429
+ printf '[defaults]\\nimage = "<your_image>"' > .fm-weck
382
430
 
383
431
  Replace <your_image> with the image you want to use.
384
432
  """
@@ -393,7 +441,7 @@ To specify an image add
393
441
  [defaults]
394
442
  image = "your_image"
395
443
 
396
- to your .weck file.
444
+ to your .fm-weck file.
397
445
  """
398
446
 
399
447
  logger.error(text, tool, config)
@@ -402,7 +450,7 @@ to your .weck file.
402
450
  def cli(raw_args: list[str]):
403
451
  help_callback, args = parse(raw_args)
404
452
  configuration = Config().load(args.config)
405
- set_log_level(args.loglevel, configuration)
453
+ set_log_options(args.loglevel, args.logfile, configuration)
406
454
  if args.dry_run:
407
455
  Config().set_dry_run(True)
408
456
 
fm_weck/config.py CHANGED
@@ -5,6 +5,7 @@
5
5
  #
6
6
  # SPDX-License-Identifier: Apache-2.0
7
7
 
8
+ import importlib.resources as pkg_resources
8
9
  import logging
9
10
  import os
10
11
  import shutil
@@ -14,8 +15,20 @@ from functools import cache
14
15
  from pathlib import Path
15
16
  from typing import Any, Callable, Iterable, Optional, Tuple, TypeVar
16
17
 
17
- import yaml
18
- from fm_tools.fmdata import FmData
18
+ try:
19
+ from fm_tools.fmdata import FmData
20
+ except ImportError:
21
+
22
+ class FmData:
23
+ def __init__(self, data, version):
24
+ raise ImportError("fm_tools is not imported.")
25
+
26
+ def get_actor_name(self):
27
+ raise ImportError("fm_tools is not imported.")
28
+
29
+ def get_version(self):
30
+ raise ImportError("fm_tools is not imported.")
31
+
19
32
 
20
33
  from fm_weck.resources import RUN_WITH_OVERLAY, RUNEXEC_SCRIPT
21
34
 
@@ -167,21 +180,30 @@ class Config(object):
167
180
  return not (sys.platform.startswith("linux") or sys.platform == "darwin")
168
181
 
169
182
  def make_runexec_script_available(self) -> Path:
170
- return self.make_script_available(RUNEXEC_SCRIPT, "runexec")
183
+ return self.make_script_available(RUNEXEC_SCRIPT)
171
184
 
172
- def make_script_available(self, source: Path = RUN_WITH_OVERLAY, target_name: str = "run_with_overlay.sh") -> Path:
185
+ def make_script_available(self, target_name: str = RUN_WITH_OVERLAY) -> Path:
173
186
  script_dir = self.cache_location / ".scripts"
174
187
  target = script_dir / target_name
188
+
175
189
  if not (target.exists() and target.is_file()):
176
190
  script_dir.mkdir(parents=True, exist_ok=True)
177
- shutil.copy(source, target)
191
+
192
+ # Try to copy from package resources
193
+ try:
194
+ with pkg_resources.path("fm_weck.resources", target_name) as source_path:
195
+ shutil.copy(source_path, target)
196
+ except FileNotFoundError:
197
+ logging.error(f"Resource {target_name} not found in package.")
198
+ return None
178
199
  else:
179
- # Compare if the RUN_WITH_OVERLAY script is newer than the existing one
180
- if source.stat().st_mtime > target.stat().st_mtime:
181
- shutil.copy(source, target)
182
- else:
183
- logging.debug("Using existing run_with_overlay.sh script")
184
- return target
200
+ # Compare modification time if the file exists
201
+ with pkg_resources.path("fm_weck.resources", target_name) as source_path:
202
+ if source_path.stat().st_mtime > target.stat().st_mtime:
203
+ shutil.copy(source_path, target)
204
+ else:
205
+ logging.debug(f"Using existing {target_name} script")
206
+ return target
185
207
 
186
208
  if Config._system_is_not_posix():
187
209
  return target
@@ -195,13 +217,16 @@ class Config(object):
195
217
  except OSError as e:
196
218
  logging.error(
197
219
  f"Failed to set executable bit: {e}. "
198
- "In some cases this can lead to permission errors when "
199
- "running the script inside of the container."
220
+ "This may lead to permission errors when running the script in the container."
200
221
  )
201
222
 
223
+ return target
224
+
202
225
 
203
226
  @cache
204
227
  def parse_fm_data(fm_data: Path, version: Optional[str]) -> FmData:
228
+ import yaml
229
+
205
230
  if not fm_data.exists() or not fm_data.is_file():
206
231
  raise FileNotFoundError(f"fm data file {fm_data} does not exist")
207
232
 
fm_weck/engine.py CHANGED
@@ -7,6 +7,7 @@
7
7
 
8
8
  import logging
9
9
  import shutil
10
+ import signal
10
11
  import subprocess
11
12
  from abc import ABC, abstractmethod
12
13
  from functools import cached_property, singledispatchmethod
@@ -14,7 +15,17 @@ from pathlib import Path
14
15
  from tempfile import mkdtemp
15
16
  from typing import List, Optional, Union
16
17
 
17
- from fm_tools.fmdata import FmData, FmImageConfig
18
+ try:
19
+ from fm_tools.fmdata import FmData, FmImageConfig
20
+ except ImportError:
21
+ # Mock the FmData and FmImageConfig class for type checking
22
+ class FmData:
23
+ def get_images(self):
24
+ pass
25
+
26
+ class FmImageConfig:
27
+ pass
28
+
18
29
 
19
30
  from fm_weck.config import Config, parse_fm_data
20
31
  from fm_weck.exceptions import NoImageError
@@ -66,6 +77,24 @@ class Engine(ABC):
66
77
  f"{source}:{target}",
67
78
  ]
68
79
 
80
+ def add_container_long_opt(self, arg: list[str]):
81
+ """
82
+ Add a long option to the container command.
83
+ If the first element of the list does not start with "--", it will be prepended.
84
+ Example:
85
+ add_container_long_opt(["--option", "value"]) -> --option value
86
+ add_container_long_opt(["option", "value"]) -> --option value
87
+ """
88
+
89
+ if not arg:
90
+ raise ValueError("Argument must not be empty.")
91
+
92
+ base = arg[0]
93
+ if not base.startswith("--"):
94
+ base = f"--{base}"
95
+
96
+ self.extra_args["container_args"] = self.extra_args.get("container_args", []) + [base] + arg[1:]
97
+
69
98
  @abstractmethod
70
99
  def benchexec_capabilities(self):
71
100
  raise NotImplementedError
@@ -261,15 +290,27 @@ class Engine(ABC):
261
290
  return tag
262
291
 
263
292
  def _run_process(self, command: tuple[str, ...] | list[str]):
293
+ process = None # To make sure process is defined if a signal is caught early
294
+
295
+ def terminate_process_group(signal_received, frame):
296
+ if process:
297
+ logging.info("Received signal %s. Terminating container process.", signal_received)
298
+ process.send_signal(signal.SIGTERM)
299
+
300
+ # Register signal handler
301
+ signal.signal(signal.SIGINT, terminate_process_group)
302
+ signal.signal(signal.SIGTERM, terminate_process_group)
303
+
304
+ logger.debug("\n\nRunning command:\n%s\n\n", " ".join(map(str, command)))
264
305
  if self.log_file is None:
265
306
  process = subprocess.Popen(command)
266
- process.wait()
267
- return
307
+ else:
308
+ self.log_file.parent.mkdir(parents=True, exist_ok=True)
309
+ with self.log_file.open("wb") as f:
310
+ process = subprocess.Popen(command, stdout=f, stderr=f)
268
311
 
269
- self.log_file.parent.mkdir(parents=True, exist_ok=True)
270
- with self.log_file.open("wb") as f:
271
- process = subprocess.Popen(command, stdout=f, stderr=f)
272
- process.wait()
312
+ assert process is not None, "Process should be defined at this point."
313
+ process.wait()
273
314
 
274
315
  def run(self, *command: str) -> None:
275
316
  if self.image is None:
@@ -279,7 +320,7 @@ class Engine(ABC):
279
320
  logger.debug("Running: %s", command)
280
321
  if self.dry_run:
281
322
  print("Command to be executed:")
282
- print(" ".join(command))
323
+ print(" ".join(map(str, command)))
283
324
  return
284
325
 
285
326
  self._run_process(command)
fm_weck/image_mgr.py CHANGED
@@ -9,8 +9,14 @@ import logging
9
9
  from pathlib import Path
10
10
  from typing import TYPE_CHECKING
11
11
 
12
- from fm_tools.fmdata import FmImageConfig
13
- from yaspin import yaspin
12
+ try:
13
+ from fm_tools.fmdata import FmImageConfig
14
+ except ImportError:
15
+
16
+ class FmImageConfig:
17
+ def __init__(self, full_images, base_images, required_packages):
18
+ raise ImportError("fm_tools is not imported.")
19
+
14
20
 
15
21
  from fm_weck.exceptions import NoImageError
16
22
 
@@ -48,6 +54,7 @@ class ImageMgr(object):
48
54
  image_cmd = engine.image_from(CONTAINERFILE)
49
55
  image_cmd.base_image(image.base_images[0])
50
56
  image_cmd.packages(image.required_packages)
57
+ from yaspin import yaspin
51
58
 
52
59
  with yaspin(text="Building image", color="cyan") as spinner:
53
60
  tag = image_cmd.build()
@@ -15,9 +15,9 @@ CONTAINERFILE = resource_dir / "Containerfile"
15
15
  # to the wheel file under fm_weck/resources/fm_tools
16
16
  FM_DATA_LOCATION = resource_dir / "fm_tools"
17
17
  PROPERTY_LOCATION = resource_dir / "properties"
18
- RUN_WITH_OVERLAY = resource_dir / "run_with_overlay.sh"
18
+ RUN_WITH_OVERLAY = "run_with_overlay.sh"
19
19
  BENCHEXEC_WHL = resource_dir / "BenchExec-3.25-py3-none-any.whl"
20
- RUNEXEC_SCRIPT = resource_dir / "runexec"
20
+ RUNEXEC_SCRIPT = "runexec"
21
21
 
22
22
 
23
23
  def iter_fm_data():
@@ -20,10 +20,28 @@ cp -r "/home/fm-weck_cache/$TOOL_DIR" /tmp/overlay/
20
20
  # Assume the user $PWD is mounted to home/cwd
21
21
  #Mount the overlay
22
22
  mount -t overlay overlay -o lowerdir=/home/cwd:/tmp/overlay/"$TOOL_DIR",upperdir=/tmp/overlay/upper,workdir=/tmp/overlay/work /home/_cwd
23
- cd /home/_cwd && "$@"
24
23
 
25
- # Fm-Weck mounts a tempdir to /home/output
26
- # Test if upper is empty
27
- if [ ! -z "$(ls -A /tmp/overlay/upper)" ]; then
24
+ # Change directory and execute the command
25
+ cd /home/_cwd || exit 1
26
+
27
+ "$@" &
28
+ PID=$!
29
+
30
+ # Handle signals and delegate to the process
31
+ trap 'kill -TERM $PID' INT TERM
32
+
33
+ # Wait for the process and handle its termination correctly
34
+ wait $PID
35
+ trap - TERM INT
36
+ wait $PID # wait for JVM to exit after signal delegation
37
+ EXIT_STATUS=$?
38
+
39
+ # Check if upper directory has data to copy to output
40
+ if [ -n "$(ls -A /tmp/overlay/upper)" ]; then
28
41
  cp -r /tmp/overlay/upper/* /home/output
29
42
  fi
43
+
44
+ # Clean up mounted filesystems
45
+ umount /tmp/overlay
46
+
47
+ exit $EXIT_STATUS
@@ -0,0 +1,52 @@
1
+ # This file is part of fm-weck: executing fm-tools in containerized environments.
2
+ # https://gitlab.com/sosy-lab/software/fm-weck
3
+ #
4
+ # SPDX-FileCopyrightText: 2024 Dirk Beyer <https://www.sosy-lab.org>
5
+ #
6
+ # SPDX-License-Identifier: Apache-2.0
7
+
8
+ import logging
9
+ import shutil
10
+ from pathlib import Path
11
+ from typing import Optional
12
+
13
+ from fm_weck.resources import BENCHEXEC_WHL
14
+ from fm_weck.runexec_util import mountable_absolute_paths_of_command
15
+
16
+ from .config import Config
17
+ from .engine import CACHE_MOUNT_LOCATION, Engine
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ def run_runexec(
23
+ benchexec_package: Optional[Path],
24
+ use_image: Optional[str],
25
+ configuration: Config,
26
+ extra_container_args: list[list[str]],
27
+ command: list[str],
28
+ ):
29
+ if use_image is not None:
30
+ configuration.set_default_image(use_image)
31
+
32
+ engine = Engine.from_config(configuration)
33
+ engine.add_benchexec_capabilities = True
34
+
35
+ if benchexec_package is not None:
36
+ engine.mount(benchexec_package.parent.absolute(), "/home/__fm_weck_benchexec")
37
+ engine.env["PYTHONPATH"] = f"/home/__fm_weck_benchexec/{benchexec_package.name}"
38
+ else:
39
+ # Default to the bundled benchexec package
40
+ benchexec_package = configuration.get_shelve_path_for_benchexec()
41
+ shutil.copyfile(BENCHEXEC_WHL, benchexec_package)
42
+ engine.env["PYTHONPATH"] = f"{CACHE_MOUNT_LOCATION}/.lib/benchexec.whl"
43
+
44
+ for path in mountable_absolute_paths_of_command(command):
45
+ engine.mount(path, path)
46
+
47
+ for arg in extra_container_args:
48
+ engine.add_container_long_opt(arg)
49
+
50
+ configuration.make_runexec_script_available()
51
+
52
+ engine.run(f"{CACHE_MOUNT_LOCATION}/.scripts/runexec", *command)
fm_weck/serve.py CHANGED
@@ -16,9 +16,6 @@ from typing import Optional, Tuple, Union
16
16
  from fm_tools import FmData
17
17
  from fm_tools.benchexec_helper import DataModel
18
18
 
19
- from fm_weck.resources import BENCHEXEC_WHL
20
- from fm_weck.runexec_util import mountable_absolute_paths_of_command
21
-
22
19
  from .config import Config, parse_fm_data
23
20
  from .engine import CACHE_MOUNT_LOCATION, Engine
24
21
 
@@ -149,27 +146,3 @@ def run_manual(
149
146
  logger.debug("Using executable %s", executable)
150
147
  logger.debug("Assembled command %s", [executable, *command])
151
148
  engine.run(executable, *command)
152
-
153
-
154
- def run_runexec(benchexec_package: Optional[Path], use_image: Optional[str], configuration: Config, command: list[str]):
155
- if use_image is not None:
156
- configuration.set_default_image(use_image)
157
-
158
- engine = Engine.from_config(configuration)
159
- engine.add_benchexec_capabilities = True
160
-
161
- if benchexec_package is not None:
162
- engine.mount(benchexec_package, "/home/__fm_weck_benchexec")
163
- engine.env["PYTHONPATH"] = "/home/__fm_weck_benchexec"
164
- else:
165
- # Default to the bundled benchexec package
166
- benchexec_package = configuration.get_shelve_path_for_benchexec()
167
- shutil.copyfile(BENCHEXEC_WHL, benchexec_package)
168
- engine.env["PYTHONPATH"] = f"{CACHE_MOUNT_LOCATION}/.lib/benchexec.whl"
169
-
170
- for path in mountable_absolute_paths_of_command(command):
171
- engine.mount(path, path)
172
-
173
- configuration.make_runexec_script_available()
174
-
175
- engine.run(f"{CACHE_MOUNT_LOCATION}/.scripts/runexec", *command)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: fm-weck
3
- Version: 1.3.0
3
+ Version: 1.4.0
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
@@ -1,17 +1,18 @@
1
- fm_weck/__init__.py,sha256=4SbQpdKol7NyPQ7_mY7VAZb-uU226i81vl4d9eNjJmA,351
1
+ fm_weck/__init__.py,sha256=fhbHcAv5kJ0_nbClYRr0E5_e6Ok5w9IOIYrtlbRYEDQ,351
2
2
  fm_weck/__main__.py,sha256=E7z4-9t6To3hbIPjRPu6iW17YCrtqpDSbFSpd9pX4NA,350
3
- fm_weck/cli.py,sha256=R8BSXFw47BqS_QUByr50PUjPcRLeXrvNCdf30ldzwWI,11956
4
- fm_weck/config.py,sha256=qO9nBoKVZSP-nE2RaJVi5bqHs4eGXEYFPWybNIzIrpQ,6619
5
- fm_weck/engine.py,sha256=GF1w0Yzcs0qS4GpGtVKJplHc3VcN4MxSavYjfiOLXJw,12162
3
+ fm_weck/cli.py,sha256=THirNpxB3jKDlKIb1Hpo3upOnsjGY7edTfqbVq7Gp1Y,13277
4
+ fm_weck/config.py,sha256=AAp5qPZfx2Gh-43jySzfHzHOEmbduHJalA7guV9SIzI,7340
5
+ fm_weck/engine.py,sha256=uaUiH1Wu7QnBwh4CEw1cdy6FtlyCfPMyU9X2m8gQWnE,13664
6
6
  fm_weck/exceptions.py,sha256=D_3xPdWkmsY4Dn7k4oGHEAZc2Ner2p3sw2t8lhEHrGI,281
7
- fm_weck/image_mgr.py,sha256=IQFQYZY4awwgCCdiIp3X0Tb-OQpRA4j8b4_MrMPD5zo,1665
7
+ fm_weck/image_mgr.py,sha256=f1RlmQPBiMrsqPyH1Rtfb8WMp2YBq-7z-Rto_kCfS7U,1861
8
+ fm_weck/runexec_mode.py,sha256=JWddzH_33O-hzjVkSVQ9-YUhEVFm23AXBBoSGmj-mvg,1697
8
9
  fm_weck/runexec_util.py,sha256=l6_3aeHg4WV6fPpRNPMzb5dGrw9aau4bDQDPi2AfLTQ,1006
9
- fm_weck/serve.py,sha256=3BCL4ufqZobxy9_QeeG2sqh1B6ns6BPhTKSTF06jZVU,6267
10
+ fm_weck/serve.py,sha256=YGGT6ULClC1vifARr5Jl0LZgS72il7nMeoo6tf76sL4,5195
10
11
  fm_weck/resources/BenchExec-3.25-py3-none-any.whl,sha256=87QrHJum5CHhpTrQlQpamHMnlkMzJE5lM4SlJg-Y9jk,718841
11
12
  fm_weck/resources/BenchExec-3.25-py3-none-any.whl.license,sha256=Nq2Mwgn_pyr6ZZrTT095QPtFP3hr15ZeIRIaY0B7eC8,201
12
13
  fm_weck/resources/Containerfile,sha256=MltxP1of9klsQFNR8WyngRTJrPwxQTF4C9ennRxVqSo,391
13
- fm_weck/resources/__init__.py,sha256=CugcM8h9LxJoCItHYji-ovVOoZhnXU2pXCtO9e38VcM,1053
14
- fm_weck/resources/run_with_overlay.sh,sha256=VwTLR5-t13HIjT08dg5kqS33NLYquxl3NmnjpJEoycg,807
14
+ fm_weck/resources/__init__.py,sha256=FiA_c0huVEKM0EKHFqzMNjq0qAYTRXvfcnHraTzj0QQ,1023
15
+ fm_weck/resources/run_with_overlay.sh,sha256=v1gV_6kMQ0v9BQ3chgDqI1MAOLHbPWeeTC52aCqVpEM,1162
15
16
  fm_weck/resources/runexec,sha256=ogIBO38HLu9C9kDTTANBgAqVnH-UIF1bSJ9d3DSjyF4,462
16
17
  fm_weck/resources/properties/coverage-branches.prp,sha256=Gl2r1cgBFoh4M2laa8dVGhteHkL04oiBRLzxz_hbkEU,56
17
18
  fm_weck/resources/properties/coverage-branches.prp.license,sha256=KzWZF1bpljIbdvwfzfWoP4DLMq6W1jXNN6WXWF0fxY0,214
@@ -129,7 +130,7 @@ fm_weck/resources/fm_tools/wasp-c.yml,sha256=NWEb2vpIBu75kZJdEq0am8Mpi2HFu5nhDI1
129
130
  fm_weck/resources/fm_tools/wit4java.yml,sha256=SukwwE46DsDmZouAwHhr_aaOjxIaeOrIS7o7P4eDWX0,1243
130
131
  fm_weck/resources/fm_tools/witch.yml,sha256=5d5aYmkrlG78M-RLdDbdi6EJWOfD0CskWtJWGXtwEyI,1152
131
132
  fm_weck/resources/fm_tools/witnesslint.yml,sha256=Y6A2TXPyjVxZ9Fhmyd7GOKY7x1_jXjshvmrIM4uW96A,3085
132
- fm_weck-1.3.0.dist-info/METADATA,sha256=CI2HfdRdHR9T-iDjt7VCJAgK6DCsqxWpPljh9vqydsg,2771
133
- fm_weck-1.3.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
134
- fm_weck-1.3.0.dist-info/entry_points.txt,sha256=toWpKCSY1u593MPnI_xW5gnwlnkerP4AvmPQ1s2nPgY,50
135
- fm_weck-1.3.0.dist-info/RECORD,,
133
+ fm_weck-1.4.0.dist-info/METADATA,sha256=Xs9-dvBYxTnLw0EmCUAkgXPO_WwK-gustbuCAhJpe_g,2771
134
+ fm_weck-1.4.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
135
+ fm_weck-1.4.0.dist-info/entry_points.txt,sha256=toWpKCSY1u593MPnI_xW5gnwlnkerP4AvmPQ1s2nPgY,50
136
+ fm_weck-1.4.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.25.0
2
+ Generator: hatchling 1.26.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any