def test_parse_parameters(self):
        from edacc.utils import parse_parameters
        params = parse_parameters("-p1 5 -p2 -p3 4.0 -p5 abc -p6 2.0")
        assert ("-p1", "-p1", "5", False, 0) in params
        assert ("-p2", "-p2", "", True, 2) in params
        assert ("-p3", "-p3", "4.0", False, 3) in params
        assert ("-p5", "-p5", "abc", False, 5) in params
        assert ("-p6", "-p6", "2.0", False, 7) in params

        params = parse_parameters("-p1 1.0 -i INSTANCE SEED")
        assert ("-p1", "-p1", "1.0", False, 0) in params
        assert ("instance", "-i", "", False, 2) in params
        assert ("seed", "", "", False, 4) in params
Example #2
0
    def test_parse_parameters(self):
        from edacc.utils import parse_parameters
        params = parse_parameters("-p1 5 -p2 -p3 4.0 -p5 abc -p6 2.0")
        assert ("-p1", "-p1", "5", False, 0) in params
        assert ("-p2", "-p2", "", True, 2) in params
        assert ("-p3", "-p3", "4.0", False, 3) in params
        assert ("-p5", "-p5", "abc", False, 5) in params
        assert ("-p6", "-p6", "2.0", False, 7) in params

        params = parse_parameters("-p1 1.0 -i INSTANCE SEED")
        assert ("-p1", "-p1", "1.0", False, 0) in params
        assert ("instance", "-i", "", False, 2) in params
        assert ("seed", "", "", False, 4) in params
Example #3
0
def submit_solver(database, id=None):
    """ Form to submit solvers to a database """
    db = models.get_database(database) or abort(404)

    # Disallow submissions of new solvers in phase 4
    if db.competition_phase() == 4 and id is None:
        abort(401)

    if id is not None:
        solver = db.session.query(db.Solver).get(id) or abort(404)
        if solver.user.idUser != g.User.idUser: abort(401)
        if db.competition_phase() == 4 and solver.competition_frozen:
            flash(
                'This solver was found to be compatible with our execution environment, i.e. has no crashed test runs or test runs with unknown result, and can not be updated anymore. Please contact the organizers if there\'s a reason to submit a new version.')
            return redirect(url_for('accounts.list_solvers',
                                    database=database, user_id=g.User.idUser))

        solver_binary = solver.binaries[0] if solver.binaries else None
        form = forms.SolverForm(request.form, solver)
        if request.method == 'GET':
            form.parameters.data = utils.parameter_template(solver)
            form.description_pdf.data = ''
            form.binary.data = ''
            form.code.data = ''
            if solver_binary:
                form.run_command.data = solver_binary.runCommand
                form.run_path.data = solver_binary.runPath
    else:
        form = forms.SolverForm()

    form.competition_categories.query = db.session.query(db.CompetitionCategory).all()

    error = None
    if form.validate_on_submit():
        valid = True # assume valid, try to falsify with the following checks

        name = form.name.data
        description = form.description.data
        version = form.version.data
        authors = form.authors.data
        parameters = form.parameters.data
        run_path = form.run_path.data

        if id is None and db.session.query(db.Solver) \
            .filter_by(name=name, version=version) \
            .first() is not None:
            error = 'Solver with this name and version already exists'
            valid = False

        if id is None and not form.code.data and not form.binary.data:
            error = 'Please provide either a binary or the code (or both).'
            valid = False

        bin = None
        if (id is None or (id is not None and form.binary.data)) and form.binary.data:
            # if this is a new solver or a resubmission with new binary update binary
            bin = request.files[form.binary.name].stream.read()
            hash = hashlib.md5()
            hash.update(bin)

            # save the binary in the FS as log
            store_path = os.path.join(config.UPLOAD_FOLDER, 'solvers',
                                      secure_filename(str(g.User.idUser) + '-' + g.User.lastname), 'bin')
            try:
                os.makedirs(store_path)
            except:
                pass
            with open(os.path.join(store_path, hash.hexdigest()), 'wb') as f:
                f.write(bin)

            if not form.binary.data.filename.endswith('.zip'):
                tmpfile = StringIO()
                zip_file = zipfile.ZipFile(tmpfile, 'w', compression=zipfile.ZIP_DEFLATED)
                zip_file.writestr(form.binary.data.filename, bin)
                zip_file.close()
                tmpfile.seek(0)
                bin = tmpfile.read()
                run_path = form.binary.data.filename
            else:
                if not run_path:
                    error = 'Since your binary is a .zip file, please provide the path of the executable within the archive'
                    valid = False

        code = None
        if id is None or (id is not None and form.code.data):
            code = request.files[form.code.name].stream.read()
            code_hash = hashlib.md5()
            code_hash.update(code)

            # save the code in the FS as log
            store_path = os.path.join(config.UPLOAD_FOLDER, 'solvers',
                                      secure_filename(str(g.User.idUser) + '-' + g.User.lastname), 'code')
            try:
                os.makedirs(store_path)
            except:
                pass
            with open(os.path.join(store_path, code_hash.hexdigest()), 'wb') as f:
                f.write(code)

        description_pdf = None
        if id is None or (id is not None and form.description_pdf.data):
            description_pdf = request.files[form.description_pdf.name].stream.read()
        if id is None and not description_pdf:
            valid = False
            error = "Please provide a description pdf."

        params = utils.parse_parameters(parameters)

        if valid:
            if id is None:
                solver = db.Solver()
                if bin:
                    solver_binary = db.SolverBinary()
                    solver_binary.solver = solver
                else:
                    solver_binary = None
            else:
                if solver_binary:
                    for solver_config in solver_binary.solver_configurations:
                        for pi in solver_config.parameter_instances: db.session.delete(pi)
                        db.session.commit()
                        db.session.delete(solver_config)
                    db.session.commit()
                if not solver_binary and bin:
                    solver_binary = db.SolverBinary()
                    solver_binary.solver = solver

            solver.name = name
            solver.description = description
            solver.authors = authors
            solver.user = g.User
            solver.version = version
            solver.competition_categories = form.competition_categories.data
            if solver_binary:
                solver_binary.binaryName = name
                solver_binary.runPath = run_path
                solver_binary.version = version
                solver_binary.runCommand = form.run_command.data
            if bin:
                # new or updated binary
                solver_binary.binaryArchive = bin
                solver_binary.md5 = hash.hexdigest()
            if code:
                # new or updated code
                solver.code = code
            if description_pdf:
                # new or updated description pdf
                solver.description_pdf = description_pdf

            db.session.add(solver)
            if bin:
                db.session.add(solver_binary)

            # on resubmissions delete old parameters
            if id is not None:
                for p in solver.parameters:
                    db.session.delete(p)
                db.session.commit()

            for p in params:
                param = db.Parameter()
                param.name = None if p[0] == '' else p[0]
                param.prefix = None if p[1] == '' else p[1]
                param.defaultValue = p[2] or ''
                param.hasValue = not p[3] # p[3] actually means 'is boolean'
                param.order = int(p[4])
                param.space = p[5]
                param.solver = solver
                db.session.add(param)
            try:
                db.session.commit()
                if code:
                    msg = Message("[" + db.label + "][Admin] Code submitted",
                                  recipients=[config.DEFAULT_MAIL_SENDER])
                    msg.body = ("The user %s %s just submitted code for the solver with id %d" % (
                    g.User.firstname, g.User.lastname, solver.idSolver))
                    mail.send(msg)
            except Exception as e:
                print e
                db.session.rollback()
                flash("Couldn't save solver to the database. Please contact an administrator for support.")
                return render('/accounts/submit_solver.html', database=database,
                              error=error, db=db, id=id, form=form)

            flash(
                'Solver submitted successfully. If you provided a binary, test jobs will be generated within the next minute. You will be notified by email once they are computed. Please check the Results page at any time for the computation progress.')
            return redirect(url_for('accounts.list_solvers',
                                    database=database, user_id=g.User.idUser))

    return render('/accounts/submit_solver.html', database=database, error=error,
                  db=db, id=id, form=form)
Example #4
0
def submit_solver(database, id=None):
    """ Form to submit solvers to a database """
    db = models.get_database(database) or abort(404)

    # Disallow submissions of new solvers in phase 4
    if db.competition_phase() == 4 and id is None:
        abort(401)

    if id is not None:
        solver = db.session.query(db.Solver).get(id) or abort(404)
        if solver.user.idUser != g.User.idUser: abort(401)
        if db.competition_phase() == 4 and solver.competition_frozen:
            flash(
                'This solver was found to be compatible with our execution environment, i.e. has no crashed test runs or test runs with unknown result, and can not be updated anymore. Please contact the organizers if there\'s a reason to submit a new version.'
            )
            return redirect(
                url_for('accounts.list_solvers',
                        database=database,
                        user_id=g.User.idUser))

        solver_binary = solver.binaries[0] if solver.binaries else None
        form = forms.SolverForm(request.form, solver)
        if request.method == 'GET':
            form.parameters.data = utils.parameter_template(solver)
            form.description_pdf.data = ''
            form.binary.data = ''
            form.code.data = ''
            if solver_binary:
                form.run_command.data = solver_binary.runCommand
                form.run_path.data = solver_binary.runPath
    else:
        form = forms.SolverForm()

    form.competition_categories.query = db.session.query(
        db.CompetitionCategory).all()

    error = None
    if form.validate_on_submit():
        valid = True  # assume valid, try to falsify with the following checks

        name = form.name.data
        description = form.description.data
        version = form.version.data
        authors = form.authors.data
        parameters = form.parameters.data
        run_path = form.run_path.data

        if id is None and db.session.query(db.Solver) \
            .filter_by(name=name, version=version) \
            .first() is not None:
            error = 'Solver with this name and version already exists'
            valid = False

        if id is None and not form.code.data and not form.binary.data:
            error = 'Please provide either a binary or the code (or both).'
            valid = False

        bin = None
        if (id is None or
            (id is not None and form.binary.data)) and form.binary.data:
            # if this is a new solver or a resubmission with new binary update binary
            bin = request.files[form.binary.name].stream.read()
            hash = hashlib.md5()
            hash.update(bin)

            # save the binary in the FS as log
            store_path = os.path.join(
                config.UPLOAD_FOLDER, 'solvers',
                secure_filename(str(g.User.idUser) + '-' + g.User.lastname),
                'bin')
            try:
                os.makedirs(store_path)
            except:
                pass
            with open(os.path.join(store_path, hash.hexdigest()), 'wb') as f:
                f.write(bin)

            if not form.binary.data.filename.endswith('.zip'):
                tmpfile = StringIO()
                zip_file = zipfile.ZipFile(tmpfile,
                                           'w',
                                           compression=zipfile.ZIP_DEFLATED)
                zip_file.writestr(form.binary.data.filename, bin)
                zip_file.close()
                tmpfile.seek(0)
                bin = tmpfile.read()
                run_path = form.binary.data.filename
            else:
                if not run_path:
                    error = 'Since your binary is a .zip file, please provide the path of the executable within the archive'
                    valid = False

        code = None
        if id is None or (id is not None and form.code.data):
            code = request.files[form.code.name].stream.read()
            code_hash = hashlib.md5()
            code_hash.update(code)

            # save the code in the FS as log
            store_path = os.path.join(
                config.UPLOAD_FOLDER, 'solvers',
                secure_filename(str(g.User.idUser) + '-' + g.User.lastname),
                'code')
            try:
                os.makedirs(store_path)
            except:
                pass
            with open(os.path.join(store_path, code_hash.hexdigest()),
                      'wb') as f:
                f.write(code)

        description_pdf = None
        if id is None or (id is not None and form.description_pdf.data):
            description_pdf = request.files[
                form.description_pdf.name].stream.read()
        if id is None and not description_pdf:
            valid = False
            error = "Please provide a description pdf."

        params = utils.parse_parameters(parameters)

        if valid:
            if id is None:
                solver = db.Solver()
                if bin:
                    solver_binary = db.SolverBinary()
                    solver_binary.solver = solver
                else:
                    solver_binary = None
            else:
                if solver_binary:
                    for solver_config in solver_binary.solver_configurations:
                        for pi in solver_config.parameter_instances:
                            db.session.delete(pi)
                        db.session.commit()
                        db.session.delete(solver_config)
                    db.session.commit()
                if not solver_binary and bin:
                    solver_binary = db.SolverBinary()
                    solver_binary.solver = solver

            solver.name = name
            solver.description = description
            solver.authors = authors
            solver.user = g.User
            solver.version = version
            solver.competition_categories = form.competition_categories.data
            if solver_binary:
                solver_binary.binaryName = name
                solver_binary.runPath = run_path
                solver_binary.version = version
                solver_binary.runCommand = form.run_command.data
            if bin:
                # new or updated binary
                solver_binary.binaryArchive = bin
                solver_binary.md5 = hash.hexdigest()
            if code:
                # new or updated code
                solver.code = code
            if description_pdf:
                # new or updated description pdf
                solver.description_pdf = description_pdf

            db.session.add(solver)
            if bin:
                db.session.add(solver_binary)

            # on resubmissions delete old parameters
            if id is not None:
                for p in solver.parameters:
                    db.session.delete(p)
                db.session.commit()

            for p in params:
                param = db.Parameter()
                param.name = None if p[0] == '' else p[0]
                param.prefix = None if p[1] == '' else p[1]
                param.defaultValue = p[2] or ''
                param.hasValue = not p[3]  # p[3] actually means 'is boolean'
                param.order = int(p[4])
                param.space = p[5]
                param.solver = solver
                db.session.add(param)
            try:
                db.session.commit()
                if code:
                    msg = Message("[" + db.label + "][Admin] Code submitted",
                                  recipients=[config.DEFAULT_MAIL_SENDER])
                    msg.body = (
                        "The user %s %s just submitted code for the solver with id %d"
                        % (g.User.firstname, g.User.lastname, solver.idSolver))
                    mail.send(msg)
            except Exception as e:
                print e
                db.session.rollback()
                flash(
                    "Couldn't save solver to the database. Please contact an administrator for support."
                )
                return render('/accounts/submit_solver.html',
                              database=database,
                              error=error,
                              db=db,
                              id=id,
                              form=form)

            flash(
                'Solver submitted successfully. If you provided a binary, test jobs will be generated within the next minute. You will be notified by email once they are computed. Please check the Results page at any time for the computation progress.'
            )
            return redirect(
                url_for('accounts.list_solvers',
                        database=database,
                        user_id=g.User.idUser))

    return render('/accounts/submit_solver.html',
                  database=database,
                  error=error,
                  db=db,
                  id=id,
                  form=form)