1
0
This repository has been archived on 2025-03-06. You can view files and clone it, but cannot push or open issues or pull requests.

151 lines
4.6 KiB
Python

from . import yaml
from . import spec
from . import helpers
from flask import Flask, request, jsonify
from glob import glob
from datetime import timedelta
import re
app = Flask(__name__)
@app.route("/")
def root():
return app.send_static_file("index.html")
@app.route("/files.json")
def files():
files = [x[5:].replace("\\", "/") for x in glob("spec/**/*.mzn", recursive=True)]
return jsonify({"files": files})
@app.route("/file.json")
def file():
path = "./spec/" + request.args["f"]
with open(path, encoding="utf-8") as file:
contents = file.read()
yaml_comment = re.match(r"\/\*\*\*\n(.*?)\n\*\*\*\/", contents, flags=re.S)
if yaml_comment is None:
return jsonify({"cases": []})
tests = [x for x in yaml.load_all(yaml_comment.group(1))]
cases = [
{
k: v
for k, v in test.__dict__.items()
if v is not yaml.Undefined
and k in ["name", "solvers", "check_against", "markers", "type",]
}
for test in tests
]
for case, test in zip(cases, tests):
case["extra_files"] = "\n".join(test.extra_files)
case["expected"] = (
[{"value": yaml.dump(expected)} for expected in test.expected]
if isinstance(test.expected, list)
else [{"value": yaml.dump(test.expected)}]
)
case["options"] = [
{"key": k, "value": (v if isinstance(v, str) else "")}
for k, v in test.options.items()
if k not in ["all_solutions", "timeout"]
]
case["all_solutions"] = (
"all_solutions" in test.options and test.options["all_solutions"]
)
case["timeout"] = (
test.options["timeout"].total_seconds()
if "timeout" in test.options
else 0
)
return jsonify({"cases": cases})
def load_spec(data):
items = {
k: v
for k, v in data.items()
if k in ["name", "solvers", "check_against", "markers", "type"]
}
items["extra_files"] = data["extra_files"].splitlines(keepends=False)
items["expected"] = [yaml.load(x["value"]) for x in data["expected"]]
items["options"] = {
x["key"]: (x["value"] if len(x["value"]) > 0 else True) for x in data["options"]
}
items["options"]["all_solutions"] = data["all_solutions"]
if not data["timeout"] == "" and float(data["timeout"]) > 0:
items["options"]["timeout"] = timedelta(seconds=float(data["timeout"]))
print(items)
return spec.Test(**items)
@app.route("/generate.json", methods=["POST"])
def generate():
path = "./spec/" + request.args["f"]
variables = request.args["vars"].splitlines(keepends=False)
mode = request.args["mode"]
data = request.json
def filter_args(solution, mode, variables):
if mode == "exclude":
for x in variables:
delattr(solution, x)
else:
all_vars = [x for x in solution.__dict__.keys()]
for x in all_vars:
if x not in variables:
delattr(solution, x)
return solution
test = load_spec(data)
generated = []
for solver in test.solvers:
model, result, required, obtained = test.run(path, solver)
if not test.passed(result):
if isinstance(obtained, spec.Result):
if isinstance(obtained.solution, list):
obtained.solution = [
filter_args(s, mode, variables) for s in obtained.solution
]
else:
filter_args(obtained.solution, mode, variables)
test.expected.append(obtained)
generated.append({"value": yaml.dump(obtained)})
return jsonify({"obtained": generated})
@app.route("/save.json", methods=["POST"])
def save():
path = "./spec/" + request.args["f"]
data = request.json
dumped = yaml.dump_all(load_spec(x) for x in data)
with open(path, encoding="utf-8", mode="r+") as file:
contents = file.read()
yaml_comment = re.match(
r"^(.*\/\*\*\*\n)(.*?)(\n\*\*\*\/.*)$", contents, flags=re.S
)
output = ""
if yaml_comment is None:
output = "/***\n" + dumped + "***/\n\n" + contents
else:
output = yaml_comment.group(1) + dumped + yaml_comment.group(3)
file.seek(0)
file.truncate()
file.write(output)
return jsonify({"status": "success"})
if __name__ == "__main__":
app.run(debug=True)