asp-chef-cli 0.5.4__tar.gz → 0.5.6__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.
- {asp_chef_cli-0.5.4 → asp_chef_cli-0.5.6}/PKG-INFO +1 -1
- {asp_chef_cli-0.5.4 → asp_chef_cli-0.5.6}/asp_chef_cli/server/routers/dumbo.py +80 -0
- {asp_chef_cli-0.5.4 → asp_chef_cli-0.5.6}/pyproject.toml +1 -1
- {asp_chef_cli-0.5.4 → asp_chef_cli-0.5.6}/LICENSE +0 -0
- {asp_chef_cli-0.5.4 → asp_chef_cli-0.5.6}/README.md +0 -0
- {asp_chef_cli-0.5.4 → asp_chef_cli-0.5.6}/asp_chef_cli/__init__.py +0 -0
- {asp_chef_cli-0.5.4 → asp_chef_cli-0.5.6}/asp_chef_cli/__main__.py +0 -0
- {asp_chef_cli-0.5.4 → asp_chef_cli-0.5.6}/asp_chef_cli/cli.py +0 -0
- {asp_chef_cli-0.5.4 → asp_chef_cli-0.5.6}/asp_chef_cli/server/__init__.py +0 -0
- {asp_chef_cli-0.5.4 → asp_chef_cli-0.5.6}/asp_chef_cli/server/dependencies.py +0 -0
- {asp_chef_cli-0.5.4 → asp_chef_cli-0.5.6}/asp_chef_cli/server/main.py +0 -0
- {asp_chef_cli-0.5.4 → asp_chef_cli-0.5.6}/asp_chef_cli/server/routers/__init__.py +0 -0
- {asp_chef_cli-0.5.4 → asp_chef_cli-0.5.6}/asp_chef_cli/server/routers/clingo.py +0 -0
- {asp_chef_cli-0.5.4 → asp_chef_cli-0.5.6}/asp_chef_cli/server/routers/opa.py +0 -0
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import json as json_module
|
|
2
2
|
import os
|
|
3
|
+
import re
|
|
3
4
|
import shutil
|
|
4
5
|
import subprocess
|
|
6
|
+
import tempfile
|
|
5
7
|
from collections import defaultdict
|
|
6
8
|
from typing import Optional, Dict, Final
|
|
7
9
|
|
|
@@ -18,6 +20,12 @@ from ..dependencies import *
|
|
|
18
20
|
router = APIRouter()
|
|
19
21
|
|
|
20
22
|
|
|
23
|
+
def strip_ansi_codes(text):
|
|
24
|
+
# This regex matches standard ANSI escape sequences
|
|
25
|
+
ansi_regex = re.compile(r'\x1b\[[0-9;]*[a-zA-Z]')
|
|
26
|
+
return ansi_regex.sub('', text)
|
|
27
|
+
|
|
28
|
+
|
|
21
29
|
@endpoint(router, "/to-zero-simplification-version/")
|
|
22
30
|
async def _(json):
|
|
23
31
|
program = SymbolicProgram.parse(json["program"])
|
|
@@ -228,6 +236,78 @@ async def _(json):
|
|
|
228
236
|
return {"models": models}
|
|
229
237
|
|
|
230
238
|
|
|
239
|
+
pasta_process: Final[Dict[str, Optional[subprocess.Popen]]] = defaultdict(lambda: None)
|
|
240
|
+
pasta_path: Final[str | None] = shutil.which("pastasolver")
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def pasta_terminate(uuid):
|
|
244
|
+
if pasta_process[uuid] is not None:
|
|
245
|
+
pasta_process[uuid].kill()
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
@endpoint(router, "/pasta/")
|
|
249
|
+
async def _(json):
|
|
250
|
+
global pasta_process
|
|
251
|
+
|
|
252
|
+
uuid = json["uuid"]
|
|
253
|
+
program = json["program"]
|
|
254
|
+
output_predicate = json["output_predicate"] or "__bounds__"
|
|
255
|
+
bound_multiplier = 0
|
|
256
|
+
try:
|
|
257
|
+
bound_multiplier = int(json["bound_multiplier"])
|
|
258
|
+
bound_multiplier = min(max(bound_multiplier, 0), 1_000_000)
|
|
259
|
+
except ValueError:
|
|
260
|
+
bound_multiplier = 0
|
|
261
|
+
|
|
262
|
+
timeout = json["timeout"]
|
|
263
|
+
if type(timeout) is not int or timeout < 1 or timeout >= 24 * 60 * 60:
|
|
264
|
+
timeout = 5
|
|
265
|
+
|
|
266
|
+
pasta_terminate(uuid)
|
|
267
|
+
|
|
268
|
+
with tempfile.NamedTemporaryFile(mode='w', delete=True) as temp_file:
|
|
269
|
+
temp_file.write(program)
|
|
270
|
+
temp_file.flush()
|
|
271
|
+
|
|
272
|
+
cmd = ["/bin/timeout", str(timeout), pasta_path, temp_file.name]
|
|
273
|
+
pasta_process[uuid] = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
274
|
+
out, err = pasta_process[uuid].communicate()
|
|
275
|
+
|
|
276
|
+
timeout_reached: Final = pasta_process[uuid].returncode == 124
|
|
277
|
+
pasta_process[uuid] = None
|
|
278
|
+
|
|
279
|
+
# report errors
|
|
280
|
+
output = out.decode()
|
|
281
|
+
lines = output.split('\n')
|
|
282
|
+
lines = [strip_ansi_codes(line) for line in lines]
|
|
283
|
+
if any(line.startswith("Error") for line in lines):
|
|
284
|
+
raise ValueError('\n' + '\n'.join(lines))
|
|
285
|
+
if timeout_reached:
|
|
286
|
+
lines = [line for line in lines if not line.startswith("Sig term")]
|
|
287
|
+
|
|
288
|
+
lines = [line for line in lines if line]
|
|
289
|
+
lb, ub = None, None
|
|
290
|
+
if len(lines) == 1:
|
|
291
|
+
lb = ub = float(lines[0].split("Lower probability == upper probability for the query: ")[1])
|
|
292
|
+
elif len(lines) == 2:
|
|
293
|
+
lb = float(lines[0].split("Lower probability for the query: ")[1])
|
|
294
|
+
ub = float(lines[1].split("Upper probability for the query: ")[1])
|
|
295
|
+
|
|
296
|
+
if lb is None or ub is None:
|
|
297
|
+
raise ValueError("Could not parse output from PASTA solver:\n" + '\n'.join(lines))
|
|
298
|
+
|
|
299
|
+
if bound_multiplier:
|
|
300
|
+
lb = round(lb * bound_multiplier)
|
|
301
|
+
ub = round(ub * bound_multiplier)
|
|
302
|
+
else:
|
|
303
|
+
lb = f'real("{lb}")'
|
|
304
|
+
ub = f'real("{ub}")'
|
|
305
|
+
|
|
306
|
+
return {"models": [
|
|
307
|
+
[f'{output_predicate}({lb},{ub})']
|
|
308
|
+
]}
|
|
309
|
+
|
|
310
|
+
|
|
231
311
|
@endpoint(router, "/template/core-template/")
|
|
232
312
|
async def _(json):
|
|
233
313
|
if not json:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|