fm-weck 1.4.7__py3-none-any.whl → 1.5.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/exceptions.py CHANGED
@@ -5,6 +5,64 @@
5
5
  #
6
6
  # SPDX-License-Identifier: Apache-2.0
7
7
 
8
+ import logging
9
+ import subprocess
10
+ import traceback
11
+ from dataclasses import dataclass
12
+ from typing import Optional
13
+
14
+ logger = logging.getLogger(__name__)
15
+
8
16
 
9
17
  class NoImageError(Exception):
10
18
  pass
19
+
20
+
21
+ class RunFailedError(Exception):
22
+ def __init__(self, exit_code, command, output=None):
23
+ super().__init__(f"Run failed with exit code {exit_code}: {output}")
24
+ self.exit_code = exit_code
25
+ self.command = command
26
+ self.output = output
27
+
28
+
29
+ @dataclass
30
+ class Failure:
31
+ kind: str # e.g., "IMAGE_NOT_FOUND", "CALLED_PROCESS_ERROR", "EXCEPTION"
32
+ message: str # short, user-facing
33
+ detail: Optional[str] = None # optional verbose info (stderr/traceback)
34
+
35
+
36
+ def failure_from_exception(e: BaseException) -> Failure:
37
+ # Special cases first
38
+ if isinstance(e, NoImageError):
39
+ failure = Failure("IMAGE_NOT_FOUND", str(e))
40
+ elif isinstance(e, RunFailedError):
41
+ failure = Failure("RUN_FAILED", f"Run failed with exit code {e.exit_code}", detail=e.output)
42
+ elif isinstance(e, subprocess.CalledProcessError):
43
+ # Try to surface stderr/stdout
44
+ stderr = e.stderr if hasattr(e, "stderr") else None
45
+ stdout = e.stdout if hasattr(e, "stdout") else None
46
+ text = stderr or stdout or str(e)
47
+ failure = Failure("CALLED_PROCESS_ERROR", f"Tool failed with exit code {e.returncode}", detail=text)
48
+ else:
49
+ # Generic fallback
50
+ failure = Failure("EXCEPTION", str(e), detail="".join(traceback.format_exception(type(e), e, e.__traceback__)))
51
+
52
+ logger.error(f"[failure] kind={failure.kind}: {failure.message}")
53
+ return failure
54
+
55
+
56
+ def failure_to_error_code(failure: "Failure"):
57
+ from fm_weck.grpc_service.proto.fm_weck_service_pb2 import ErrorCode
58
+
59
+ FAILURE_KIND_TO_ERROR_CODE = {
60
+ "RUN_NOT_TERMINATED": ErrorCode.EC_RUN_NOT_TERMINATED,
61
+ "RUN_NOT_FOUND": ErrorCode.EC_RUN_NOT_FOUND,
62
+ "RUN_CANCELLED": ErrorCode.EC_RUN_CANCELLED,
63
+ "RUN_FAILED": ErrorCode.EC_RUN_FAILED,
64
+ "CALLED_PROCESS_ERROR": ErrorCode.EC_RUN_FAILED,
65
+ "IMAGE_NOT_FOUND": ErrorCode.EC_RUN_FAILED,
66
+ "EXCEPTION": ErrorCode.EC_UNKNOWN_ERROR,
67
+ }
68
+ return FAILURE_KIND_TO_ERROR_CODE.get(failure.kind, ErrorCode.EC_RUN_FAILED)
fm_weck/file_util.py ADDED
@@ -0,0 +1,28 @@
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
+ from pathlib import Path
9
+
10
+ # replacement strings
11
+ WINDOWS_LINE_ENDING = b"\r\n"
12
+ UNIX_LINE_ENDING = b"\n"
13
+
14
+
15
+ def copy_ensuring_unix_line_endings(src: Path, dst: Path) -> None:
16
+ with open(src, "rb") as src_file:
17
+ content = src_file.read()
18
+
19
+ # Windows ➡ Unix
20
+ content = content.replace(WINDOWS_LINE_ENDING, UNIX_LINE_ENDING)
21
+
22
+ with open(dst, "wb") as dst_file:
23
+ dst_file.write(content)
24
+
25
+
26
+ def ensure_linux_style(path: str) -> str:
27
+ """Ensure that the given path uses Linux-style forward slashes."""
28
+ return path.replace("\\", "/")
@@ -0,0 +1,9 @@
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
+ from .fm_weck_client import client_expert_run, client_get_run, client_run, query_files # noqa: F401
9
+ from .fm_weck_server import serve # noqa: F401
@@ -0,0 +1,148 @@
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
+ from pathlib import Path
9
+ from typing import Tuple
10
+
11
+ import grpc
12
+
13
+ from .proto.fm_weck_service_pb2 import (
14
+ CancelRunRequest,
15
+ ExpertRunRequest,
16
+ FileQuery,
17
+ Property,
18
+ RunID,
19
+ RunRequest,
20
+ ToolType,
21
+ WaitParameters,
22
+ )
23
+ from .proto.fm_weck_service_pb2_grpc import FmWeckRemoteStub
24
+
25
+
26
+ def start_run(stub, tool, prop, c_program):
27
+ with open(tool[0], "rb") as tool_file, open(prop, "rb") as property_file:
28
+ tool_bin = tool_file.read()
29
+ prop_bin = property_file.read()
30
+
31
+ tool_data: ToolType = ToolType(tool_version=tool[1], tool_file={"name": "fm-tool.yml", "file": tool_bin})
32
+ prop_data: Property = Property(property_file={"name": "property.prp", "file": prop_bin})
33
+ run_info = RunRequest(tool=tool_data, property=prop_data, c_program=c_program, data_model="ILP32")
34
+ run_id = stub.startRun(run_info)
35
+
36
+ return run_id
37
+
38
+
39
+ def start_expert_run(stub, tool, command):
40
+ with open(tool[0], "rb") as tool_file:
41
+ tool_bin = tool_file.read()
42
+
43
+ tool_data: ToolType = ToolType(tool_version=tool[1], tool_file={"name": "fm-tool.yml", "file": tool_bin})
44
+ expert_run_info = ExpertRunRequest(tool=tool_data, command=command)
45
+ run_id = stub.startExpertRun(expert_run_info)
46
+
47
+ return run_id
48
+
49
+
50
+ def cancel_run(stub, run_id, confirmed=True):
51
+ if confirmed:
52
+ stub.cancelRun(CancelRunRequest(run_id=run_id, timeout=5, cleanup_on_success=True))
53
+
54
+
55
+ def wait_on_run(stub, run_id, timelimit):
56
+ response = stub.waitOnRun(WaitParameters(run_id=run_id, timeout=timelimit))
57
+
58
+ if not response:
59
+ print("Server timed out or returned no files.")
60
+ exit(1)
61
+
62
+ if response.error:
63
+ print(response.error, ": Error occurred on the server side.")
64
+ exit(response.error)
65
+ elif response.timeout:
66
+ print("Run timed out.")
67
+ exit(1)
68
+
69
+ if not response.run_result.success:
70
+ print("There was an error running the tool.")
71
+ exit(1)
72
+
73
+ print()
74
+ print(response.run_result.output)
75
+ if response.run_result.filenames:
76
+ print("The run produced the following files:")
77
+ print(response.run_result.filenames)
78
+ print(
79
+ "\nFiles can be obtained by running:\nfm-weck query-files [-h] --host HOST [--timelimit TIMELIMIT]"
80
+ "[--output-path OUTPUT_PATH] RUN-ID [files ...]"
81
+ )
82
+ else:
83
+ print("The run produced no files.")
84
+ print()
85
+
86
+ return response
87
+
88
+
89
+ def query_files(host: str, run_id: str, file_names: str, timelimit: int, output_path: Path):
90
+ print("Establishing a connection to the server ...")
91
+ with grpc.insecure_channel(host) as channel:
92
+ stub = FmWeckRemoteStub(channel)
93
+
94
+ run_id = RunID(run_id=run_id)
95
+ try:
96
+ wait_on_run(stub, run_id, timelimit)
97
+ except KeyboardInterrupt:
98
+ cancel_run(stub, run_id)
99
+
100
+ request = FileQuery(filenames=file_names, run_id=run_id)
101
+ responses = stub.queryFiles(request)
102
+
103
+ output_path = output_path / "fm_weck_server_files" / run_id.run_id
104
+ output_path.mkdir(exist_ok=True, parents=True)
105
+ for response in responses:
106
+ with open(output_path / response.name, "wb") as output_file:
107
+ output_file.write(response.file)
108
+
109
+
110
+ def client_run(tool: Tuple[Path, str], host: str, prop: Path, files: list[Path], timelimit: int):
111
+ with open(files[0], "rb") as c_file:
112
+ c_program = c_file.read()
113
+
114
+ print("Establishing a connection to the server ...")
115
+ with grpc.insecure_channel(host) as channel:
116
+ stub = FmWeckRemoteStub(channel)
117
+
118
+ run_id = start_run(stub, tool, prop, c_program)
119
+ print("Run ID: ", run_id.run_id)
120
+ try:
121
+ wait_on_run(stub, run_id, timelimit)
122
+ except KeyboardInterrupt:
123
+ cancel_run(stub, run_id)
124
+
125
+
126
+ def client_expert_run(tool: Tuple[Path, str], host: str, command: list[str], timelimit: int):
127
+ print("Establishing a connection to the server ...")
128
+ with grpc.insecure_channel(host) as channel:
129
+ stub = FmWeckRemoteStub(channel)
130
+
131
+ run_id = start_expert_run(stub, tool, command)
132
+ print("Run ID: ", run_id.run_id)
133
+ try:
134
+ wait_on_run(stub, run_id, timelimit)
135
+ except KeyboardInterrupt:
136
+ cancel_run(stub, run_id)
137
+
138
+
139
+ def client_get_run(host: str, run_id: str, timelimit: int):
140
+ print("Establishing a connection to the server ...")
141
+ with grpc.insecure_channel(host) as channel:
142
+ stub = FmWeckRemoteStub(channel)
143
+
144
+ run_id = RunID(run_id=run_id)
145
+ try:
146
+ wait_on_run(stub, run_id, timelimit)
147
+ except KeyboardInterrupt:
148
+ cancel_run(stub, run_id)
@@ -0,0 +1,175 @@
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
+ from concurrent import futures
9
+ from pathlib import Path
10
+ from typing import Generator
11
+
12
+ import grpc
13
+
14
+ from fm_weck.exceptions import failure_to_error_code
15
+
16
+ from . import run_store as RunStore
17
+ from .proto.fm_weck_service_pb2 import (
18
+ CancelRunRequest,
19
+ CancelRunResult,
20
+ CleanUpResponse,
21
+ ErrorCode,
22
+ ExpertRunRequest,
23
+ File,
24
+ FileQuery,
25
+ RunID,
26
+ RunRequest,
27
+ RunResult,
28
+ WaitParameters,
29
+ WaitRunResult,
30
+ )
31
+ from .proto.fm_weck_service_pb2_grpc import FmWeckRemoteServicer, add_FmWeckRemoteServicer_to_server
32
+ from .request_handling import RunHandler, StillRunningError
33
+ from .server_utils import (
34
+ logger,
35
+ read_file,
36
+ )
37
+
38
+
39
+ class FmWeckRemote(FmWeckRemoteServicer):
40
+ def startRun(self, request: RunRequest, context) -> RunID:
41
+ run_handler = RunHandler(request)
42
+ run_handler.start()
43
+
44
+ run_id = RunStore.add_run(run_handler)
45
+
46
+ return RunID(run_id=run_id)
47
+
48
+ def startExpertRun(self, request: ExpertRunRequest, context) -> RunID:
49
+ run_handler = RunHandler(request)
50
+ run_handler.start_expert(request.command)
51
+
52
+ run_id = RunStore.add_run(run_handler)
53
+
54
+ return RunID(run_id=run_id)
55
+
56
+ def cancelRun(self, request: CancelRunRequest, context) -> CancelRunResult:
57
+ run_handler = RunStore.get_run(request.run_id.run_id)
58
+
59
+ if not run_handler:
60
+ return CancelRunResult(error=ErrorCode.EC_RUN_NOT_FOUND)
61
+
62
+ if run_handler.is_running():
63
+ run_handler.cancel_run()
64
+ # Wait a short amount of time. For most cases, the run should be canceled by now.
65
+ try:
66
+ run_handler.join(request.timeout)
67
+ except TimeoutError:
68
+ return CancelRunResult(timeout=True)
69
+
70
+ if request.cleanup_on_success:
71
+ run_handler.cleanup()
72
+
73
+ return CancelRunResult(run_result=self._run_result_from_handler(run_handler))
74
+
75
+ def waitOnRun(self, request: WaitParameters, context) -> WaitRunResult:
76
+ logger.info("waitOnRun called for run_id=%s, timeout=%s", request.run_id.run_id, request.timeout)
77
+ run_handler = RunStore.get_run(request.run_id.run_id)
78
+
79
+ if run_handler is None:
80
+ logger.info("waitOnRun: run not found (run_id=%s)", request.run_id.run_id)
81
+ return WaitRunResult(error=ErrorCode.EC_RUN_NOT_FOUND)
82
+
83
+ try:
84
+ run_handler.join(request.timeout)
85
+ except TimeoutError:
86
+ logger.info("waitOnRun: timeout (run_id=%s)", request.run_id.run_id)
87
+ return WaitRunResult(timeout=True)
88
+
89
+ if run_handler.ready() and not run_handler._success:
90
+ failure = run_handler.failure()
91
+ error_code = failure_to_error_code(failure) if failure else ErrorCode.EC_UNKNOWN_ERROR
92
+ logger.info("waitOnRun: failed (run_id=%s)", request.run_id.run_id)
93
+ return WaitRunResult(error=error_code)
94
+
95
+ logger.info("waitOnRun: success (run_id=%s)", request.run_id.run_id)
96
+ return WaitRunResult(run_result=self._run_result_from_handler(run_handler))
97
+
98
+ def queryFiles(self, query: FileQuery, context) -> Generator[File, None, None]:
99
+ run_handler = RunStore.get_run(query.run_id.run_id)
100
+ if run_handler is None:
101
+ return
102
+
103
+ filenames_to_consider = query.filenames or []
104
+ name_patterns_to_consider = query.name_patterns or []
105
+
106
+ for file_name in filenames_to_consider:
107
+ try:
108
+ file = run_handler.get_file(file_name)
109
+ yield self._file_from_path(file)
110
+ except FileNotFoundError:
111
+ continue
112
+
113
+ for name_pattern in name_patterns_to_consider:
114
+ for file in run_handler.glob(name_pattern):
115
+ yield self._file_from_path(file)
116
+
117
+ # The empty query returns all files.
118
+ if len(filenames_to_consider) == 0 and len(name_patterns_to_consider) == 0:
119
+ files_generator = self._all_files_from_path(run_handler._output_dir)
120
+ for file in files_generator:
121
+ yield file
122
+
123
+ def cleanupRun(self, request: RunID, context):
124
+ run_handler = RunStore.get_run(request.run_id)
125
+
126
+ if run_handler is None:
127
+ return CleanUpResponse(success=False, error=ErrorCode.EC_RUN_NOT_FOUND)
128
+
129
+ try:
130
+ run_handler.cleanup()
131
+ except StillRunningError:
132
+ return CleanUpResponse(success=False, error=ErrorCode.EC_RUN_NOT_TERMINATED)
133
+
134
+ RunStore.remove_run(request.run_id)
135
+
136
+ return CleanUpResponse(success=True)
137
+
138
+ @staticmethod
139
+ def _file_from_path(file_path: str | Path) -> File:
140
+ if isinstance(file_path, str):
141
+ file_path = Path(file_path)
142
+
143
+ return File(name=file_path.name, file=read_file(file_path))
144
+
145
+ @staticmethod
146
+ def _all_files_from_path(directory_path: str | Path):
147
+ if isinstance(directory_path, str):
148
+ directory_path = Path(directory_path)
149
+
150
+ for file_path in directory_path.rglob("*"):
151
+ if file_path.is_file():
152
+ yield FmWeckRemote._file_from_path(file_path)
153
+
154
+ @staticmethod
155
+ def _run_result_from_handler(run_handler: RunHandler) -> RunResult:
156
+ return RunResult(
157
+ run_id=RunID(run_id=run_handler.run_id),
158
+ success=run_handler.ready() and run_handler.successful(),
159
+ output=run_handler.output,
160
+ filenames=run_handler.output_files,
161
+ )
162
+
163
+
164
+ def serve(ipaddr: str, port: str):
165
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
166
+ add_FmWeckRemoteServicer_to_server(FmWeckRemote(), server)
167
+ server.add_insecure_port(f"{ipaddr}:{port}")
168
+ server.start()
169
+ logger.info("Server started, listening on " + port)
170
+ try:
171
+ server.wait_for_termination()
172
+ except KeyboardInterrupt:
173
+ logger.info("Shutting down the server...")
174
+ server.stop(grace=0)
175
+ logger.info("Server successfully shut down.")
File without changes
@@ -0,0 +1,139 @@
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
+ syntax = "proto3";
9
+
10
+ // This service runs fm-weck remotely.
11
+
12
+ service FmWeckRemote {
13
+ // Runs a verification task for a given C program.
14
+ rpc startRun(RunRequest) returns (RunID) {}
15
+
16
+ // Runs a tool in expert mode
17
+ rpc startExpertRun(ExpertRunRequest) returns (RunID) {}
18
+
19
+ // Cancels a previously started run.
20
+ rpc cancelRun(CancelRunRequest) returns (CancelRunResult) {}
21
+
22
+ // Cleans up files of a finished run.
23
+ rpc cleanupRun(RunID) returns (CleanUpResponse) {}
24
+
25
+ // Gets the result of a previously started run using its unique ID.
26
+ rpc waitOnRun(WaitParameters) returns (WaitRunResult) {}
27
+
28
+ // Query for a number of result files.
29
+ rpc queryFiles(FileQuery) returns (stream File) {}
30
+ }
31
+
32
+ message ToolType {
33
+ optional string tool_version = 1;
34
+ oneof tool_data {
35
+ File tool_file = 2;
36
+ string tool_id = 3;
37
+ }
38
+ }
39
+
40
+ message Property {
41
+ oneof property {
42
+ string property_id = 1;
43
+ File property_file = 2;
44
+ }
45
+ }
46
+
47
+ message RunRequest {
48
+ ToolType tool = 1;
49
+ Property property = 2;
50
+ bytes c_program = 4;
51
+ string data_model = 5;
52
+ }
53
+
54
+ message ExpertRunRequest{
55
+ ToolType tool = 1;
56
+ repeated string command = 2;
57
+ }
58
+
59
+ message RunResult {
60
+ RunID run_id = 1;
61
+ // Whether the run was successful or terminated with an error
62
+ bool success = 2;
63
+ // The output produced by fm-weck
64
+ string output = 3;
65
+ // List of files produced by the run; may be empty
66
+ repeated string filenames = 4;
67
+ }
68
+
69
+ message WaitRunResult {
70
+ // Whether the request has timed out or not
71
+ oneof result {
72
+ bool timeout = 1;
73
+ ErrorCode error = 2;
74
+ RunResult run_result = 3;
75
+ }
76
+ }
77
+
78
+ message CancelRunRequest {
79
+ RunID run_id = 1;
80
+ // Timeout in seconds to wait for completion of the cancellation
81
+ uint32 timeout = 2;
82
+ // If true, the run is cleaned up on the server side
83
+ optional bool cleanup_on_success = 3;
84
+ }
85
+
86
+ message CancelRunResult {
87
+ oneof result {
88
+ // Whether the could be canceled completely
89
+ // or is still shutting down.
90
+ // If True, then the run is canceled on the server side, but complete shutdown may take some time.
91
+ // Call waitOnRun if the termination must be confirmed.
92
+ bool timeout = 1;
93
+ ErrorCode error = 2;
94
+ RunResult run_result = 3;
95
+ }
96
+ }
97
+
98
+ enum ErrorCode {
99
+ // The run is not terminated yet
100
+ EC_RUN_NOT_TERMINATED = 0;
101
+ EC_RUN_NOT_FOUND = 1;
102
+ EC_RUN_CANCELLED = 2;
103
+ EC_RUN_FAILED = 3;
104
+ EC_UNKNOWN_ERROR = 4;
105
+ }
106
+
107
+ message CleanUpResponse {
108
+ // If cleanup was successful, this field is true
109
+ // Then no errors are reported.
110
+ bool success = 1;
111
+ // If success is false, this field contains the error code
112
+ optional ErrorCode error = 2;
113
+ }
114
+
115
+ message RunID {
116
+ string run_id = 1;
117
+ }
118
+
119
+ message WaitParameters {
120
+ //Timeout in seconds to wait for the run to finish
121
+ uint32 timeout = 1;
122
+ RunID run_id = 2;
123
+ }
124
+
125
+ message FileQuery {
126
+ // If the run_id does not exist, the server will return an empty stream.
127
+ RunID run_id = 3;
128
+
129
+ // Non existent files are ignored.
130
+ repeated string filenames = 1;
131
+ repeated string name_patterns = 2;
132
+ }
133
+
134
+ message File {
135
+ string name = 1;
136
+ bytes file = 2;
137
+ }
138
+
139
+ message Empty {}
@@ -0,0 +1,73 @@
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
+ # -*- coding: utf-8 -*-
9
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
10
+ # NO CHECKED-IN PROTOBUF GENCODE
11
+ # source: fm_weck_service.proto
12
+ # Protobuf Python Version: 5.29.0
13
+ """Generated protocol buffer code."""
14
+ from google.protobuf import descriptor as _descriptor
15
+ from google.protobuf import descriptor_pool as _descriptor_pool
16
+ from google.protobuf import runtime_version as _runtime_version
17
+ from google.protobuf import symbol_database as _symbol_database
18
+ from google.protobuf.internal import builder as _builder
19
+ _runtime_version.ValidateProtobufRuntimeVersion(
20
+ _runtime_version.Domain.PUBLIC,
21
+ 5,
22
+ 29,
23
+ 0,
24
+ '',
25
+ 'fm_weck_service.proto'
26
+ )
27
+ # @@protoc_insertion_point(imports)
28
+
29
+ _sym_db = _symbol_database.Default()
30
+
31
+
32
+
33
+
34
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66m_weck_service.proto\"r\n\x08ToolType\x12\x19\n\x0ctool_version\x18\x01 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\ttool_file\x18\x02 \x01(\x0b\x32\x05.FileH\x00\x12\x11\n\x07tool_id\x18\x03 \x01(\tH\x00\x42\x0b\n\ttool_dataB\x0f\n\r_tool_version\"M\n\x08Property\x12\x15\n\x0bproperty_id\x18\x01 \x01(\tH\x00\x12\x1e\n\rproperty_file\x18\x02 \x01(\x0b\x32\x05.FileH\x00\x42\n\n\x08property\"i\n\nRunRequest\x12\x17\n\x04tool\x18\x01 \x01(\x0b\x32\t.ToolType\x12\x1b\n\x08property\x18\x02 \x01(\x0b\x32\t.Property\x12\x11\n\tc_program\x18\x04 \x01(\x0c\x12\x12\n\ndata_model\x18\x05 \x01(\t\"<\n\x10\x45xpertRunRequest\x12\x17\n\x04tool\x18\x01 \x01(\x0b\x32\t.ToolType\x12\x0f\n\x07\x63ommand\x18\x02 \x03(\t\"W\n\tRunResult\x12\x16\n\x06run_id\x18\x01 \x01(\x0b\x32\x06.RunID\x12\x0f\n\x07success\x18\x02 \x01(\x08\x12\x0e\n\x06output\x18\x03 \x01(\t\x12\x11\n\tfilenames\x18\x04 \x03(\t\"k\n\rWaitRunResult\x12\x11\n\x07timeout\x18\x01 \x01(\x08H\x00\x12\x1b\n\x05\x65rror\x18\x02 \x01(\x0e\x32\n.ErrorCodeH\x00\x12 \n\nrun_result\x18\x03 \x01(\x0b\x32\n.RunResultH\x00\x42\x08\n\x06result\"s\n\x10\x43\x61ncelRunRequest\x12\x16\n\x06run_id\x18\x01 \x01(\x0b\x32\x06.RunID\x12\x0f\n\x07timeout\x18\x02 \x01(\r\x12\x1f\n\x12\x63leanup_on_success\x18\x03 \x01(\x08H\x00\x88\x01\x01\x42\x15\n\x13_cleanup_on_success\"m\n\x0f\x43\x61ncelRunResult\x12\x11\n\x07timeout\x18\x01 \x01(\x08H\x00\x12\x1b\n\x05\x65rror\x18\x02 \x01(\x0e\x32\n.ErrorCodeH\x00\x12 \n\nrun_result\x18\x03 \x01(\x0b\x32\n.RunResultH\x00\x42\x08\n\x06result\"L\n\x0f\x43leanUpResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x1e\n\x05\x65rror\x18\x02 \x01(\x0e\x32\n.ErrorCodeH\x00\x88\x01\x01\x42\x08\n\x06_error\"\x17\n\x05RunID\x12\x0e\n\x06run_id\x18\x01 \x01(\t\"9\n\x0eWaitParameters\x12\x0f\n\x07timeout\x18\x01 \x01(\r\x12\x16\n\x06run_id\x18\x02 \x01(\x0b\x32\x06.RunID\"M\n\tFileQuery\x12\x16\n\x06run_id\x18\x03 \x01(\x0b\x32\x06.RunID\x12\x11\n\tfilenames\x18\x01 \x03(\t\x12\x15\n\rname_patterns\x18\x02 \x03(\t\"\"\n\x04\x46ile\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04\x66ile\x18\x02 \x01(\x0c\"\x07\n\x05\x45mpty*{\n\tErrorCode\x12\x19\n\x15\x45\x43_RUN_NOT_TERMINATED\x10\x00\x12\x14\n\x10\x45\x43_RUN_NOT_FOUND\x10\x01\x12\x14\n\x10\x45\x43_RUN_CANCELLED\x10\x02\x12\x11\n\rEC_RUN_FAILED\x10\x03\x12\x14\n\x10\x45\x43_UNKNOWN_ERROR\x10\x04\x32\x93\x02\n\x0c\x46mWeckRemote\x12!\n\x08startRun\x12\x0b.RunRequest\x1a\x06.RunID\"\x00\x12-\n\x0estartExpertRun\x12\x11.ExpertRunRequest\x1a\x06.RunID\"\x00\x12\x32\n\tcancelRun\x12\x11.CancelRunRequest\x1a\x10.CancelRunResult\"\x00\x12(\n\ncleanupRun\x12\x06.RunID\x1a\x10.CleanUpResponse\"\x00\x12.\n\twaitOnRun\x12\x0f.WaitParameters\x1a\x0e.WaitRunResult\"\x00\x12#\n\nqueryFiles\x12\n.FileQuery\x1a\x05.File\"\x00\x30\x01\x62\x06proto3')
35
+
36
+ _globals = globals()
37
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
38
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'fm_weck_service_pb2', _globals)
39
+ if not _descriptor._USE_C_DESCRIPTORS:
40
+ DESCRIPTOR._loaded_options = None
41
+ _globals['_ERRORCODE']._serialized_start=1101
42
+ _globals['_ERRORCODE']._serialized_end=1224
43
+ _globals['_TOOLTYPE']._serialized_start=25
44
+ _globals['_TOOLTYPE']._serialized_end=139
45
+ _globals['_PROPERTY']._serialized_start=141
46
+ _globals['_PROPERTY']._serialized_end=218
47
+ _globals['_RUNREQUEST']._serialized_start=220
48
+ _globals['_RUNREQUEST']._serialized_end=325
49
+ _globals['_EXPERTRUNREQUEST']._serialized_start=327
50
+ _globals['_EXPERTRUNREQUEST']._serialized_end=387
51
+ _globals['_RUNRESULT']._serialized_start=389
52
+ _globals['_RUNRESULT']._serialized_end=476
53
+ _globals['_WAITRUNRESULT']._serialized_start=478
54
+ _globals['_WAITRUNRESULT']._serialized_end=585
55
+ _globals['_CANCELRUNREQUEST']._serialized_start=587
56
+ _globals['_CANCELRUNREQUEST']._serialized_end=702
57
+ _globals['_CANCELRUNRESULT']._serialized_start=704
58
+ _globals['_CANCELRUNRESULT']._serialized_end=813
59
+ _globals['_CLEANUPRESPONSE']._serialized_start=815
60
+ _globals['_CLEANUPRESPONSE']._serialized_end=891
61
+ _globals['_RUNID']._serialized_start=893
62
+ _globals['_RUNID']._serialized_end=916
63
+ _globals['_WAITPARAMETERS']._serialized_start=918
64
+ _globals['_WAITPARAMETERS']._serialized_end=975
65
+ _globals['_FILEQUERY']._serialized_start=977
66
+ _globals['_FILEQUERY']._serialized_end=1054
67
+ _globals['_FILE']._serialized_start=1056
68
+ _globals['_FILE']._serialized_end=1090
69
+ _globals['_EMPTY']._serialized_start=1092
70
+ _globals['_EMPTY']._serialized_end=1099
71
+ _globals['_FMWECKREMOTE']._serialized_start=1227
72
+ _globals['_FMWECKREMOTE']._serialized_end=1502
73
+ # @@protoc_insertion_point(module_scope)