예제 #1
0
파일: util.py 프로젝트: PJeBeK/cms
class CommonRequestHandler(RequestHandler):
    """Encapsulates shared RequestHandler functionality.

    """

    # Whether the login cookie duration has to be refreshed when
    # this handler is called. Useful to filter asynchronous
    # requests.
    refresh_cookie = True

    def __init__(self, *args, **kwargs):
        super(CommonRequestHandler, self).__init__(*args, **kwargs)
        self.timestamp = None
        self.sql_session = None
        self.r_params = None
        self.contest = None
        self.url = None

    def prepare(self):
        """This method is executed at the beginning of each request.

        """
        super(CommonRequestHandler, self).prepare()
        self.timestamp = make_datetime()
        self.set_header("Cache-Control", "no-cache, must-revalidate")
        self.sql_session = Session()
        self.sql_session.expire_all()
        self.url = create_url_builder(get_url_root(self.request.path))

    @property
    def service(self):
        return self.application.service
예제 #2
0
파일: task.py 프로젝트: ioi-israel/cms
class AddStatementHandler(BaseHandler):
    """Add a statement to a task.

    """

    @require_permission(BaseHandler.PERMISSION_ALL)
    def get(self, task_id):
        task = self.safe_get_item(Task, task_id)

        self.r_params = self.render_params()
        self.r_params["task"] = task
        self.render("add_statement.html", **self.r_params)

    @require_permission(BaseHandler.PERMISSION_ALL)
    def post(self, task_id):
        fallback_page = "/task/%s/statements/add" % task_id

        task = self.safe_get_item(Task, task_id)

        language = self.get_argument("language", None)
        if language is None:
            self.application.service.add_notification(
                make_datetime(), "No language code specified",
                "The language code can be any string.")
            self.redirect(fallback_page)
            return
        statement = self.request.files["statement"][0]
        if not statement["filename"].endswith(".pdf"):
            self.application.service.add_notification(
                make_datetime(), "Invalid task statement",
                "The task statement must be a .pdf file.")
            self.redirect(fallback_page)
            return
        task_name = task.name
        self.sql_session.close()

        try:
            digest = self.application.service.file_cacher.put_file_content(
                statement["body"],
                "Statement for task %s (lang: %s)" % (task_name, language))
        except Exception as error:
            self.application.service.add_notification(
                make_datetime(), "Task statement storage failed", repr(error))
            self.redirect(fallback_page)
            return

        # TODO verify that there's no other Statement with that language
        # otherwise we'd trigger an IntegrityError for constraint violation

        self.sql_session = Session()
        task = self.safe_get_item(Task, task_id)
        self.contest = task.contest

        statement = Statement(language, digest, task=task)
        self.sql_session.add(statement)

        if self.try_commit():
            self.redirect("/task/%s" % task_id)
        else:
            self.redirect(fallback_page)
예제 #3
0
    def post(self, dataset_id):
        fallback_page = self.url("dataset", dataset_id, "testcases", "add")

        dataset = self.safe_get_item(Dataset, dataset_id)
        task = dataset.task

        codename = self.get_argument("codename")

        try:
            input_ = self.request.files["input"][0]
            output = self.request.files["output"][0]
        except KeyError:
            self.service.add_notification(
                make_datetime(),
                "Invalid data",
                "Please fill both input and output.")
            self.redirect(fallback_page)
            return

        public = self.get_argument("public", None) is not None
        task_name = task.name
        self.sql_session.close()

        try:
            input_digest = \
                self.service.file_cacher.put_file_content(
                    input_["body"],
                    "Testcase input for task %s" % task_name)
            output_digest = \
                self.service.file_cacher.put_file_content(
                    output["body"],
                    "Testcase output for task %s" % task_name)
        except Exception as error:
            self.service.add_notification(
                make_datetime(),
                "Testcase storage failed",
                repr(error))
            self.redirect(fallback_page)
            return

        self.sql_session = Session()
        dataset = self.safe_get_item(Dataset, dataset_id)
        task = dataset.task

        testcase = Testcase(
            codename, public, input_digest, output_digest, dataset=dataset)
        self.sql_session.add(testcase)

        if self.try_commit():
            # max_score and/or extra_headers might have changed.
            self.service.proxy_service.reinitialize()
            self.redirect(self.url("task", task.id))
        else:
            self.redirect(fallback_page)
예제 #4
0
class CommonRequestHandler(RequestHandler):
    """Encapsulates shared RequestHandler functionality.

    """

    # Whether the login cookie duration has to be refreshed when
    # this handler is called. Useful to filter asynchronous
    # requests.
    refresh_cookie = True

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.timestamp = make_datetime()
        self.endofday = make_endofday_datetime()
        self.sql_session = Session()
        self.r_params = None
        self.contest = None
        self.url = None

    def prepare(self):
        """This method is executed at the beginning of each request.

        """
        super().prepare()
        self.url = Url(get_url_root(self.request.path))
        self.set_header("Cache-Control", "no-cache, must-revalidate")

    def finish(self, *args, **kwargs):
        """Finish this response, ending the HTTP request.

        We override this method in order to properly close the database.

        TODO - Now that we have greenlet support, this method could be
        refactored in terms of context manager or something like
        that. So far I'm leaving it to minimize changes.

        """
        if self.sql_session is not None:
            try:
                self.sql_session.close()
            except Exception as error:
                logger.warning("Couldn't close SQL connection: %r", error)
        try:
            super().finish(*args, **kwargs)
        except OSError:
            # When the client closes the connection before we reply,
            # Tornado raises an OSError exception, that would pollute
            # our log with unnecessarily critical messages
            logger.debug("Connection closed before our reply.")

    @property
    def service(self):
        return self.application.service
예제 #5
0
파일: util.py 프로젝트: cms-dev/cms
class CommonRequestHandler(RequestHandler):
    """Encapsulates shared RequestHandler functionality.

    """

    # Whether the login cookie duration has to be refreshed when
    # this handler is called. Useful to filter asynchronous
    # requests.
    refresh_cookie = True

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.timestamp = make_datetime()
        self.sql_session = Session()
        self.r_params = None
        self.contest = None
        self.url = None

    def prepare(self):
        """This method is executed at the beginning of each request.

        """
        super().prepare()
        self.url = Url(get_url_root(self.request.path))
        self.set_header("Cache-Control", "no-cache, must-revalidate")

    def finish(self, *args, **kwargs):
        """Finish this response, ending the HTTP request.

        We override this method in order to properly close the database.

        TODO - Now that we have greenlet support, this method could be
        refactored in terms of context manager or something like
        that. So far I'm leaving it to minimize changes.

        """
        if self.sql_session is not None:
            try:
                self.sql_session.close()
            except Exception as error:
                logger.warning("Couldn't close SQL connection: %r", error)
        try:
            super().finish(*args, **kwargs)
        except OSError:
            # When the client closes the connection before we reply,
            # Tornado raises an OSError exception, that would pollute
            # our log with unnecessarily critical messages
            logger.debug("Connection closed before our reply.")

    @property
    def service(self):
        return self.application.service
예제 #6
0
    def test_yaowei(self):

        from cms.db.orm import YaoWei
        yaowei = YaoWei("酸")
        Session.add(yaowei)
        Session.commit()
        suan = Session.query(YaoWei).filter(YaoWei.wei == "酸").all()
        self.assertEqual(len(suan), 1)
        for xing in suan:
            Session.delete(xing)
        Session.commit()
        suan = Session.query(YaoWei).all()
        self.assertEqual(bool(suan), False)
예제 #7
0
    def test_dizhi(self):

        from cms.db.orm import DiZhi

        dizhi = DiZhi("中国", "湖南", "湘潭市", "湘潭县云湖桥镇北岸村道林组83号")
        Session.add(dizhi)
        Session.commit()
        items = Session.query(DiZhi.jiedao).filter(DiZhi.sheng == "湖南").first()
        self.assertEqual(items[0], u"湘潭县云湖桥镇北岸村道林组83号")
        items = Session.query(DiZhi).all()
        for m in items:
            Session.delete(m)
        Session.commit()
예제 #8
0
    def test_jingluo(self):

        from cms.db.orm import JingLuo
        item = JingLuo("足少阳胆经")
        Session.add(item)
        Session.commit()
        items = Session.query(JingLuo).filter(
            JingLuo.mingcheng == "足少阳胆经").all()
        self.assertEqual(len(items), 1)
        for m in items:
            Session.delete(m)
        Session.commit()
        items = Session.query(JingLuo).all()
        self.assertEqual(bool(items), False)
예제 #9
0
    def post(self, task_id):
        fallback_page = self.url("task", task_id, "statements", "add")

        task = self.safe_get_item(Task, task_id)

        language = self.get_argument("language", "")
        if len(language) == 0:
            self.service.add_notification(
                make_datetime(),
                "No language code specified",
                "The language code can be any string.")
            self.redirect(fallback_page)
            return
        statement = self.request.files["statement"][0]
        if not statement["filename"].endswith(".pdf"):
            self.service.add_notification(
                make_datetime(),
                "Invalid task statement",
                "The task statement must be a .pdf file.")
            self.redirect(fallback_page)
            return
        task_name = task.name
        self.sql_session.close()

        try:
            digest = self.service.file_cacher.put_file_content(
                statement["body"],
                "Statement for task %s (lang: %s)" % (task_name, language))
        except Exception as error:
            self.service.add_notification(
                make_datetime(),
                "Task statement storage failed",
                repr(error))
            self.redirect(fallback_page)
            return

        # TODO verify that there's no other Statement with that language
        # otherwise we'd trigger an IntegrityError for constraint violation

        self.sql_session = Session()
        task = self.safe_get_item(Task, task_id)
        self.contest = task.contest

        statement = Statement(language, digest, task=task)
        self.sql_session.add(statement)

        if self.try_commit():
            self.redirect(self.url("task", task_id))
        else:
            self.redirect(fallback_page)
예제 #10
0
파일: dataset.py 프로젝트: cms-dev/cms
class AddManagerHandler(BaseHandler):
    """Add a manager to a dataset.

    """
    @require_permission(BaseHandler.PERMISSION_ALL)
    def get(self, dataset_id):
        dataset = self.safe_get_item(Dataset, dataset_id)
        task = dataset.task
        self.contest = task.contest

        self.r_params = self.render_params()
        self.r_params["task"] = task
        self.r_params["dataset"] = dataset
        self.render("add_manager.html", **self.r_params)

    @require_permission(BaseHandler.PERMISSION_ALL)
    def post(self, dataset_id):
        fallback_page = self.url("dataset", dataset_id, "managers", "add")

        dataset = self.safe_get_item(Dataset, dataset_id)
        task = dataset.task

        manager = self.request.files["manager"][0]
        task_name = task.name
        self.sql_session.close()

        try:
            digest = self.service.file_cacher.put_file_content(
                manager["body"],
                "Task manager for %s" % task_name)
        except Exception as error:
            self.service.add_notification(
                make_datetime(),
                "Manager storage failed",
                repr(error))
            self.redirect(fallback_page)
            return

        self.sql_session = Session()
        dataset = self.safe_get_item(Dataset, dataset_id)
        task = dataset.task

        manager = Manager(manager["filename"], digest, dataset=dataset)
        self.sql_session.add(manager)

        if self.try_commit():
            self.redirect(self.url("task", task.id))
        else:
            self.redirect(fallback_page)
예제 #11
0
class AddManagerHandler(BaseHandler):
    """Add a manager to a dataset.

    """
    @require_permission(BaseHandler.PERMISSION_ALL)
    def get(self, dataset_id):
        dataset = self.safe_get_item(Dataset, dataset_id)
        task = dataset.task
        self.contest = task.contest

        self.r_params = self.render_params()
        self.r_params["task"] = task
        self.r_params["dataset"] = dataset
        self.render("add_manager.html", **self.r_params)

    @require_permission(BaseHandler.PERMISSION_ALL)
    def post(self, dataset_id):
        fallback_page = self.url("dataset", dataset_id, "managers", "add")

        dataset = self.safe_get_item(Dataset, dataset_id)
        task = dataset.task

        manager = self.request.files["manager"][0]
        task_name = task.name
        self.sql_session.close()

        try:
            digest = self.service.file_cacher.put_file_content(
                manager["body"],
                "Task manager for %s" % task_name)
        except Exception as error:
            self.service.add_notification(
                make_datetime(),
                "Manager storage failed",
                repr(error))
            self.redirect(fallback_page)
            return

        self.sql_session = Session()
        dataset = self.safe_get_item(Dataset, dataset_id)
        task = dataset.task

        manager = Manager(manager["filename"], digest, dataset=dataset)
        self.sql_session.add(manager)

        if self.try_commit():
            self.redirect(self.url("task", task.id))
        else:
            self.redirect(fallback_page)
예제 #12
0
    def prepare(self):
        """This method is executed at the beginning of each request.

        """
        self.timestamp = make_datetime()

        self.set_header("Cache-Control", "no-cache, must-revalidate")

        self.sql_session = Session()
        self.contest = Contest.get_from_id(self.application.service.contest,
                                           self.sql_session)

        self._ = self.locale.translate

        self.r_params = self.render_params()
예제 #13
0
class AddAttachmentHandler(BaseHandler):
    """Add an attachment to a task.

    """
    @require_permission(BaseHandler.PERMISSION_ALL)
    def get(self, task_id):
        task = self.safe_get_item(Task, task_id)
        self.contest = task.contest

        self.r_params = self.render_params()
        self.r_params["task"] = task
        self.render("add_attachment.html", **self.r_params)

    @require_permission(BaseHandler.PERMISSION_ALL)
    def post(self, task_id):
        fallback_page = self.url("task", task_id, "attachments", "add")

        task = self.safe_get_item(Task, task_id)

        attachment = self.request.files["attachment"][0]
        task_name = task.name
        self.sql_session.close()

        try:
            digest = self.service.file_cacher.put_file_content(
                attachment["body"],
                "Task attachment for %s" % task_name)
        except Exception as error:
            self.service.add_notification(
                make_datetime(),
                "Attachment storage failed",
                repr(error))
            self.redirect(fallback_page)
            return

        # TODO verify that there's no other Attachment with that filename
        # otherwise we'd trigger an IntegrityError for constraint violation

        self.sql_session = Session()
        task = self.safe_get_item(Task, task_id)

        attachment = Attachment(attachment["filename"], digest, task=task)
        self.sql_session.add(attachment)

        if self.try_commit():
            self.redirect(self.url("task", task_id))
        else:
            self.redirect(fallback_page)
예제 #14
0
파일: task.py 프로젝트: ioi-germany/cms
class AddSpoilerHandler(BaseHandler):
    """Add a spoiler to a task.

    """
    @require_permission(BaseHandler.PERMISSION_ALL)
    def get(self, task_id):
        task = self.safe_get_item(Task, task_id)
        self.contest = task.contest

        self.r_params = self.render_params()
        self.r_params["task"] = task
        self.render("add_spoiler.html", **self.r_params)

    @require_permission(BaseHandler.PERMISSION_ALL)
    def post(self, task_id):
        fallback_page = self.url("task", task_id, "spoiler", "add")

        task = self.safe_get_item(Task, task_id)

        spoiler = self.request.files["spoiler"][0]
        task_name = task.name
        self.sql_session.close()

        try:
            digest = self.service.file_cacher.put_file_content(
                spoiler["body"],
                "Task spoiler for %s" % task_name)
        except Exception as error:
            self.service.add_notification(
                make_datetime(),
                "Spoiler storage failed",
                repr(error))
            self.redirect(fallback_page)
            return

        # TODO verify that there's no other Spoiler with that filename
        # otherwise we'd trigger an IntegrityError for constraint violation

        self.sql_session = Session()
        task = self.safe_get_item(Task, task_id)

        spoiler = Spoiler(spoiler["filename"], digest, task=task)
        self.sql_session.add(spoiler)

        if self.try_commit():
            self.redirect(self.url("task", task_id))
        else:
            self.redirect(fallback_page)
예제 #15
0
파일: task.py 프로젝트: ioi-germany/cms
    def post(self, task_id):
        fallback_page = self.url("task", task_id, "spoiler", "add")

        task = self.safe_get_item(Task, task_id)

        spoiler = self.request.files["spoiler"][0]
        task_name = task.name
        self.sql_session.close()

        try:
            digest = self.service.file_cacher.put_file_content(
                spoiler["body"],
                "Task spoiler for %s" % task_name)
        except Exception as error:
            self.service.add_notification(
                make_datetime(),
                "Spoiler storage failed",
                repr(error))
            self.redirect(fallback_page)
            return

        # TODO verify that there's no other Spoiler with that filename
        # otherwise we'd trigger an IntegrityError for constraint violation

        self.sql_session = Session()
        task = self.safe_get_item(Task, task_id)

        spoiler = Spoiler(spoiler["filename"], digest, task=task)
        self.sql_session.add(spoiler)

        if self.try_commit():
            self.redirect(self.url("task", task_id))
        else:
            self.redirect(fallback_page)
예제 #16
0
파일: util.py 프로젝트: cms-dev/cms
 def __init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     self.timestamp = make_datetime()
     self.sql_session = Session()
     self.r_params = None
     self.contest = None
     self.url = None
예제 #17
0
파일: dataset.py 프로젝트: artikz/cms
    def post(self, dataset_id):
        fallback_page = "/dataset/%s/managers/add" % dataset_id

        dataset = self.safe_get_item(Dataset, dataset_id)
        task = dataset.task

        manager = self.request.files["manager"][0]
        task_name = task.name
        self.sql_session.close()

        try:
            digest = self.application.service.file_cacher.put_file_content(
                manager["body"],
                "Task manager for %s" % task_name)
        except Exception as error:
            self.application.service.add_notification(
                make_datetime(),
                "Manager storage failed",
                repr(error))
            self.redirect(fallback_page)
            return

        self.sql_session = Session()
        dataset = self.safe_get_item(Dataset, dataset_id)
        task = dataset.task

        manager = Manager(manager["filename"], digest, dataset=dataset)
        self.sql_session.add(manager)

        if self.try_commit():
            self.redirect("/task/%s" % task.id)
        else:
            self.redirect(fallback_page)
예제 #18
0
파일: task.py 프로젝트: mvpossum/cms-oia
    def post(self, task_id):
        fallback_page = "/task/%s/attachments/add" % task_id

        task = self.safe_get_item(Task, task_id)

        attachment = self.request.files["attachment"][0]
        task_name = task.name
        self.sql_session.close()

        try:
            digest = self.application.service.file_cacher.put_file_content(
                attachment["body"],
                "Task attachment for %s" % task_name)
        except Exception as error:
            self.application.service.add_notification(
                make_datetime(),
                "Attachment storage failed",
                repr(error))
            self.redirect(fallback_page)
            return

        # TODO verify that there's no other Attachment with that filename
        # otherwise we'd trigger an IntegrityError for constraint violation

        self.sql_session = Session()
        task = self.safe_get_item(Task, task_id)

        attachment = Attachment(attachment["filename"], digest, task=task)
        self.sql_session.add(attachment)

        if self.try_commit():
            self.redirect("/task/%s" % task_id)
        else:
            self.redirect(fallback_page)
예제 #19
0
class CommonRequestHandler(RequestHandler):
    """Encapsulates shared RequestHandler functionality.

    """

    # Whether the login cookie duration has to be refreshed when
    # this handler is called. Useful to filter asynchronous
    # requests.
    refresh_cookie = True

    def __init__(self, *args, **kwargs):
        super(CommonRequestHandler, self).__init__(*args, **kwargs)
        self.timestamp = None
        self.sql_session = None
        self.r_params = None
        self.contest = None

    def prepare(self):
        """This method is executed at the beginning of each request.

        """
        super(CommonRequestHandler, self).prepare()
        self.timestamp = make_datetime()
        self.set_header("Cache-Control", "no-cache, must-revalidate")
        self.sql_session = Session()
        self.sql_session.expire_all()

    @property
    def service(self):
        return self.application.service

    def redirect(self, url):
        url = get_url_root(self.request.path) + url

        # We would prefer to just use this:
        #   tornado.web.RequestHandler.redirect(self, url)
        # but unfortunately that assumes it knows the full path to the current
        # page to generate an absolute URL. This may not be the case if we are
        # hidden behind a proxy which is remapping part of its URL space to us.

        self.set_status(302)
        self.set_header("Location", url)
        self.finish()
예제 #20
0
    def empty_tables(self, tbls=None):
        """drop all db tables
        """

        #         tbls = ['Yao_ChuFang_Asso','ChuFang','Yao_JingLuo_Asso','Yao','YaoWei','YaoXing','JingLuo']
        tbls = [
            'YaoWei', 'YaoXing', 'JingLuo', 'Yao_JingLuo_Asso', 'Yao',
            'Yao_ChuFang_Asso', 'ChuFang_BingRen_Asso', 'ChuFang', 'YiSheng',
            'DanWei', 'DiZhi', 'BingRen'
        ]
        items = []
        for tb in tbls:
            import_str = "from %(p)s import %(t)s as tablecls" % dict(
                p='cms.db.orm', t=tb)
            exec import_str
            items.extend(Session.query(tablecls).all())
        for m in items:
            Session.delete(m)
        Session.commit()
예제 #21
0
    def test_import_with_drop(self):
        """Test importing everything, but dropping existing data."""
        self.write_dump(TestDumpImporter.DUMP)
        self.write_files(TestDumpImporter.FILES)

        # Need to close the session and reopen it, otherwise the drop hangs.
        self.session.close()
        self.assertTrue(self.do_import(drop=True))
        self.session = Session()

        self.assertContestInDb("contestname", "contest description 你好",
                               [("taskname", "task title")],
                               [("username", "Last Name")])
        self.assertContestNotInDb(self.other_contest_name)

        self.assertFileInDb(TestDumpImporter.GENERATED_FILE_DIGEST, "desc",
                            b"content")
        self.assertFileInDb(TestDumpImporter.NOT_GENERATED_FILE_DIGEST,
                            "subsource", b"source")
예제 #22
0
    def test_bingren(self):

        from cms.db.orm import ChuFang, BingRen, DiZhi

        dizhi = DiZhi("中国", "湖南", "湘潭市", "湘潭县云湖桥镇北岸村道林组83号")
        bingren = BingRen('张三', 1, date(2015, 4, 2), '13673265899')
        bingren.dizhi = dizhi
        Session.add(bingren)
        Session.commit()
        items = Session.query(BingRen).filter(
            BingRen.dianhua == "13673265899").first()
        self.assertEqual(items.dizhi.jiedao, u"湘潭县云湖桥镇北岸村道林组83号")

        items = Session.query(BingRen).join(DiZhi).filter(
            DiZhi.sheng == "湖南").first()
        self.assertEqual(items.dizhi.jiedao, u"湘潭县云湖桥镇北岸村道林组83号")

        items = Session.query(BingRen).all()
        items.extend(Session.query(DiZhi).all())

        for m in items:
            Session.delete(m)
        Session.commit()
예제 #23
0
    def test_asso_chufang_bingren(self):

        from cms.db.orm import ChuFang,DanWei,\
        BingRen,DiZhi,YiSheng,ChuFang_BingRen_Asso,YaoWei,YaoXing,JingLuo,Yao,Yao_ChuFang_Asso

        dizhi = DiZhi("中国", "湖南", "湘潭市", "湘潭县云湖桥镇北岸村道林组83号")
        bingren = BingRen('张三', 1, date(2015, 4, 2), '13673265899')
        bingren.dizhi = dizhi
        dizhi2 = DiZhi("中国", "湖北", "十堰市", "茅箭区施洋路83号")
        danwei = DanWei("任之堂")
        yisheng = YiSheng('余浩', 1, date(2015, 4, 2), '13673265859')
        danwei.yishengs = [yisheng]
        danwei.dizhi = dizhi2
        yaowei = YaoWei("酸")
        yaoxing = YaoXing("寒")
        jingluo = JingLuo("足厥阴肝经")
        yao = Yao("白芍")
        chufang = ChuFang("桂枝汤")
        yao.yaowei = yaowei
        yao.yaoxing = yaoxing
        yao.guijing = [jingluo]
        yao_chufang = Yao_ChuFang_Asso(yao, chufang, 7, "加热稀粥")

        chufang_bingren = ChuFang_BingRen_Asso(bingren, chufang,
                                               datetime.now())
        # many to many association table don't add to session
        #         Session.add(Yao_ChuFang_Asso)
        #         Session.add(ChuFang_BingRen_Asso)
        Session.add(yaowei)
        Session.add(yaoxing)
        Session.add(jingluo)
        Session.add(yao)
        Session.add(chufang)
        Session.add(yao_chufang)
        Session.add(dizhi)
        Session.add(bingren)
        Session.add(dizhi2)
        Session.add(danwei)
        Session.add(yisheng)
        Session.add(chufang_bingren)

        Session.commit()
        items = Session.query(BingRen).filter(
            BingRen.dianhua == "13673265899").first()
        self.assertEqual(items.dizhi.jiedao, u"湘潭县云湖桥镇北岸村道林组83号")

        items = Session.query(BingRen).join(DiZhi).filter(
            DiZhi.sheng == "湖南").first()
        self.assertEqual(items.dizhi.jiedao, u"湘潭县云湖桥镇北岸村道林组83号")

        items = Session.query(Yao).all()
        items.extend(Session.query(YaoXing).all())
        items.extend(Session.query(YaoWei).all())
        items.extend(Session.query(JingLuo).all())
        items.extend(Session.query(ChuFang).all())
        items.extend(Session.query(BingRen).all())
        items.extend(Session.query(YiSheng).all())
        items.extend(Session.query(DanWei).all())
        items.extend(Session.query(DiZhi).all())
        for m in items:
            Session.delete(m)
        Session.commit()
예제 #24
0
    def test_all_tables(self):

        from cms.db.orm import ChuFang,DanWei,\
        BingRen,DiZhi,YiSheng,ChuFang_BingRen_Asso,YaoWei,YaoXing,JingLuo,Yao,Yao_ChuFang_Asso

        dizhi = DiZhi("中国", "湖南", "湘潭市", "湘潭县云湖桥镇北岸村道林组83号")
        bingren = BingRen('张三', 1, date(2015, 4, 2), '13673265899')
        bingren.dizhi = dizhi
        dizhi2 = DiZhi("中国", "湖北", "十堰市", "茅箭区施洋路83号")
        danwei = DanWei("任之堂")
        yisheng = YiSheng('余浩', 1, date(2015, 4, 2), '13673265859')
        danwei.yishengs = [yisheng]
        danwei.dizhi = dizhi2
        yaowei = YaoWei("酸")
        yaoxing = YaoXing("寒")
        jingluo = JingLuo("足厥阴肝经")
        yao = Yao("白芍")
        yaowei2 = YaoWei("甘")
        yaoxing2 = YaoXing("温")
        jingluo2 = JingLuo("足太阴脾经")
        yao2 = Yao("大枣")
        chufang = ChuFang("桂枝汤")
        yao2.yaowei = yaowei2
        yao2.yaoxing = yaoxing2
        yao2.guijing = [jingluo2]
        yao.yaowei = yaowei
        yao.yaoxing = yaoxing
        yao.guijing = [jingluo]
        yao_chufang = Yao_ChuFang_Asso(yao, chufang, 7, "加热稀粥")
        yao_chufang2 = Yao_ChuFang_Asso(yao2, chufang, 10, "掰开")

        chufang_bingren = ChuFang_BingRen_Asso(bingren, chufang,
                                               datetime.now())
        yisheng.chufangs = [chufang]

        Session.add_all([yaowei, yaoxing, jingluo, yao, chufang, yao_chufang])
        Session.add_all([yaowei2, yaoxing2, jingluo2, yao2, yao_chufang2])
        Session.add(dizhi)
        Session.add(bingren)
        Session.add(dizhi2)
        Session.add(danwei)
        Session.add(yisheng)
        Session.add(chufang_bingren)

        Session.commit()
        items = Session.query(BingRen).filter(
            BingRen.dianhua == "13673265899").first()
        self.assertEqual(items.dizhi.jiedao, u"湘潭县云湖桥镇北岸村道林组83号")

        items = Session.query(BingRen).join(DiZhi).filter(
            DiZhi.sheng == "湖南").first()
        self.assertEqual(items.dizhi.jiedao, u"湘潭县云湖桥镇北岸村道林组83号")
        items = Session.query(ChuFang).join(YiSheng).filter(
            YiSheng.xingming == "余浩").first()
        import pdb
        pdb.set_trace()

        self.assertEqual(len(items.yaoes), 2)
        self.assertEqual(items.yishengxm, "余浩")

        items = Session.query(Yao).all()
        items.extend(Session.query(YaoXing).all())
        items.extend(Session.query(YaoWei).all())
        items.extend(Session.query(JingLuo).all())
        items.extend(Session.query(ChuFang).all())
        items.extend(Session.query(BingRen).all())
        items.extend(Session.query(YiSheng).all())
        items.extend(Session.query(DanWei).all())
        items.extend(Session.query(DiZhi).all())
        for m in items:
            Session.delete(m)
        Session.commit()
예제 #25
0
 def setUp(self):
     super(DatabaseMixin, self).setUp()
     self.session = Session()
예제 #26
0
class DatabaseMixin(DatabaseObjectGeneratorMixin):
    """Mixin for tests with database access."""
    @classmethod
    def setUpClass(cls):
        super(DatabaseMixin, cls).setUpClass()
        assert "fortesting" in str(cms.db.engine), \
            "Monkey patching of DB connection string failed"
        drop_db()
        init_db()
        cls.connection = cms.db.engine.connect()
        cms.db.metadata.create_all(cls.connection)

    @classmethod
    def tearDownClass(cls):
        drop_db()
        cls.connection.close()
        cms.db.engine.dispose()
        super(DatabaseMixin, cls).tearDownClass()

    def setUp(self):
        super(DatabaseMixin, self).setUp()
        self.session = Session()

    def tearDown(self):
        self.session.rollback()
        super(DatabaseMixin, self).tearDown()

    def delete_data(self):
        """Delete all the data in the DB.

        This is useful to call during tear down, for tests that rely on
        starting from a clean DB.

        """
        for table in itervalues(Base.metadata.tables):
            self.session.execute(table.delete())
        self.session.commit()

    @staticmethod
    def add_fsobject(digest, content):
        dbbackend = DBBackend()
        fobj = dbbackend.create_file(digest)
        fobj.write(content)
        dbbackend.commit_file(fobj, digest)

    def add_contest(self, **kwargs):
        """Create a contest and add it to the session"""
        contest = self.get_contest(**kwargs)
        self.session.add(contest)
        return contest

    def add_announcement(self, **kwargs):
        """Create an announcement and add it to the session"""
        announcement = self.get_announcement(**kwargs)
        self.session.add(announcement)
        return announcement

    def add_user(self, **kwargs):
        """Create a user and add it to the session"""
        user = self.get_user(**kwargs)
        self.session.add(user)
        return user

    def add_participation(self, **kwargs):
        """Create a participation and add it to the session"""
        participation = self.get_participation(**kwargs)
        self.session.add(participation)
        return participation

    def add_message(self, **kwargs):
        """Create a message and add it to the session"""
        message = self.get_message(**kwargs)
        self.session.add(message)
        return message

    def add_question(self, **kwargs):
        """Create a question and add it to the session"""
        question = self.get_question(**kwargs)
        self.session.add(question)
        return question

    def add_task(self, **kwargs):
        """Create a task and add it to the session"""
        task = self.get_task(**kwargs)
        self.session.add(task)
        return task

    def add_statement(self, task=None, **kwargs):
        """Create a statement and add it to the session"""
        task = task if task is not None else self.add_task()
        args = {
            "task": task,
            "digest": unique_digest(),
            "language": unique_unicode_id(),
        }
        args.update(kwargs)
        statement = Statement(**args)
        self.session.add(statement)
        return statement

    def add_dataset(self, **kwargs):
        """Create a dataset and add it to the session"""
        dataset = self.get_dataset(**kwargs)
        self.session.add(dataset)
        return dataset

    def add_manager(self, dataset=None, **kwargs):
        """Create a manager and add it to the session."""
        manager = self.get_manager(dataset=dataset, **kwargs)
        self.session.add(manager)
        return manager

    def add_testcase(self, dataset=None, **kwargs):
        """Add a testcase."""
        dataset = dataset if dataset is not None else self.add_dataset()
        args = {
            "dataset": dataset,
            "codename": unique_unicode_id(),
            "input": unique_digest(),
            "output": unique_digest(),
        }
        args.update(kwargs)
        testcase = Testcase(**args)
        self.session.add(testcase)
        return testcase

    def add_submission(self, task=None, participation=None, **kwargs):
        """Add a submission."""
        submission = self.get_submission(task, participation, **kwargs)
        self.session.add(submission)
        return submission

    def add_file(self, submission=None, **kwargs):
        """Create a file and add it to the session"""
        if submission is None:
            submission = self.add_submission()
        args = {
            "submission": submission,
            "filename": unique_unicode_id(),
            "digest": unique_digest(),
        }
        args.update(kwargs)
        file_ = File(**args)
        self.session.add(file_)
        return file_

    def add_token(self, submission=None, **kwargs):
        """Create a token and add it to the session"""
        token = self.get_token(submission, **kwargs)
        self.session.add(token)
        return token

    def add_submission_result(self, submission=None, dataset=None, **kwargs):
        """Add a submission result."""
        submission_result = self.get_submission_result(submission, dataset,
                                                       **kwargs)
        self.session.add(submission_result)
        return submission_result

    def add_executable(self, submission_result=None, **kwargs):
        """Create an executable and add it to the session"""
        submission_result = submission_result \
            if submission_result is not None \
            else self.add_submission_result()
        args = {
            "submission_result": submission_result,
            "digest": unique_digest(),
            "filename": unique_unicode_id(),
        }
        args.update(kwargs)
        executable = Executable(**args)
        self.session.add(executable)
        return executable

    def add_evaluation(self, submission_result=None, testcase=None, **kwargs):
        """Add an evaluation."""
        dataset = None
        dataset = submission_result.dataset \
            if submission_result is not None else dataset
        dataset = testcase.dataset if testcase is not None else dataset
        submission_result = submission_result \
            if submission_result is not None \
            else self.add_submission_result(dataset=dataset)
        testcase = testcase if testcase is not None else self.add_testcase()
        assert submission_result.dataset == testcase.dataset
        args = {
            "submission_result": submission_result,
            "testcase": testcase,
        }
        args.update(kwargs)
        evaluation = Evaluation(**args)
        self.session.add(evaluation)
        return evaluation

    def add_user_test(self, task=None, participation=None, **kwargs):
        """Add a user test."""
        if task is None:
            task = self.add_task(contest=self.add_contest())
        participation = participation \
            if participation is not None \
            else self.add_participation(contest=task.contest)
        assert task.contest == participation.contest
        args = {
            "task": task,
            "participation": participation,
            "input": unique_digest(),
            "timestamp": (task.contest.start + timedelta(0, unique_long_id())),
        }
        args.update(kwargs)
        user_test = UserTest(**args)
        self.session.add(user_test)
        return user_test

    def add_user_test_file(self, user_test=None, **kwargs):
        """Create a user test file and add it to the session"""
        if user_test is None:
            user_test = self.add_user_test()
        args = {
            "user_test": user_test,
            "filename": unique_unicode_id(),
            "digest": unique_digest(),
        }
        args.update(kwargs)
        user_test_file = UserTestFile(**args)
        self.session.add(user_test_file)
        return user_test_file

    def add_user_test_manager(self, user_test=None, **kwargs):
        """Create a user test manager and add it to the session"""
        if user_test is None:
            user_test = self.add_user_test()
        args = {
            "user_test": user_test,
            "filename": unique_unicode_id(),
            "digest": unique_digest(),
        }
        args.update(kwargs)
        user_test_manager = UserTestManager(**args)
        self.session.add(user_test_manager)
        return user_test_manager

    def add_user_test_result(self, user_test=None, dataset=None, **kwargs):
        """Add a user test result."""
        task = None
        task = user_test.task if user_test is not None else task
        task = dataset.task if dataset is not None else task
        user_test = user_test \
            if user_test is not None else self.add_user_test(task=task)
        dataset = dataset \
            if dataset is not None else self.add_dataset(task=task)
        assert user_test.task == dataset.task
        args = {
            "user_test": user_test,
            "dataset": dataset,
        }
        args.update(kwargs)
        user_test_result = UserTestResult(**args)
        self.session.add(user_test_result)
        return user_test_result

    # Other commonly used generation functions.

    def add_submission_with_results(self,
                                    task,
                                    participation,
                                    compilation_outcome=None):
        """Add a submission for the tasks, all of its results, and optionally
        the compilation outcome for all results.

        """
        submission = self.add_submission(task, participation)
        results = [
            self.add_submission_result(submission, dataset)
            for dataset in task.datasets
        ]
        if compilation_outcome is not None:
            for result in results:
                result.set_compilation_outcome(compilation_outcome)
        return submission, results

    def add_user_test_with_results(self, compilation_outcome=None):
        """Add a user_test for the first tasks, all of its results, and
        optionally the compilation outcome for all results.

        """
        user_test = self.add_user_test(self.tasks[0], self.participation)
        results = [
            self.add_user_test_result(user_test, dataset)
            for dataset in self.tasks[0].datasets
        ]
        if compilation_outcome is not None:
            for result in results:
                result.set_compilation_outcome(compilation_outcome)
        return user_test, results

    def add_team(self, **kwargs):
        """Create a team and add it to the session"""
        team = self.get_team(**kwargs)
        self.session.add(team)
        return team
예제 #27
0
    return l[0], "\n".join(l[1:])

def bold(s):
    return "*" + s + "*"

def italic(s):
    return "_" + s + "_"

def escape(s):
    return "".join("\\" + c if ord(c) > 32 and ord(c) < 127 else c for c in s)

def code(s):
    linebreak = "" if len(s) > 0 and s[-1] == "\n" else "\n"
    return "```\n" + s + linebreak + "```\n"

_session = Session()


class WithDatabaseAccess(object):
    """ Base class for database access
    """
    def __init__(self, sql_session):
        self.sql_session = sql_session

    def _commit(self):
        self.sql_session.commit()


class MyQuestion(WithDatabaseAccess):
    """ Thin wrapper around question
    """
예제 #28
0
파일: task.py 프로젝트: apsc160/cms
class AddStatementHandler(BaseHandler):
    """Add a statement to a task.

    """
    @require_permission(BaseHandler.PERMISSION_ALL)
    def get(self, task_id):
        task = self.safe_get_item(Task, task_id)
        self.contest = task.contest

        self.r_params = self.render_params()
        self.r_params["task"] = task
        self.render("add_statement.html", **self.r_params)

    @require_permission(BaseHandler.PERMISSION_ALL)
    def post(self, task_id):
        fallback_page = self.url("task", task_id, "statements", "add")

        task = self.safe_get_item(Task, task_id)

        language = self.get_argument("language", "")
        if len(language) == 0:
            self.service.add_notification(
                make_datetime(),
                "No language code specified",
                "The language code can be any string.")
            self.redirect(fallback_page)
            return
        statement = self.request.files["statement"][0]

        # check statement type
        statement_type = get_statement_type(statement["filename"])        
        if statement_type is None:
            valid_types = "|".join(get_valid_statement_types())
            self.service.add_notification(
                make_datetime(),
                "Invalid task statement",
                "The task statement must be of a supported file type (" + valid_types + ").")
            self.redirect(fallback_page)
            return

        task_name = task.name
        self.sql_session.close()

        try:
            digest = self.service.file_cacher.put_file_content(
                statement["body"],
                "Statement for task %s (lang: %s)" % (task_name, language))
        except Exception as error:
            self.service.add_notification(
                make_datetime(),
                "Task statement storage failed",
                repr(error))
            self.redirect(fallback_page)
            return

        # TODO verify that there's no other Statement with that language
        # otherwise we'd trigger an IntegrityError for constraint violation

        self.sql_session = Session()
        task = self.safe_get_item(Task, task_id)
        self.contest = task.contest

        statement = Statement(language, statement_type=statement_type, digest=digest, task=task)
        self.sql_session.add(statement)

        if self.try_commit():
            self.redirect(self.url("task", task_id))
        else:
            self.redirect(fallback_page)
예제 #29
0
    def test_yisheng(self):

        from cms.db.orm import DiZhi, DanWei, YiSheng

        dizhi = DiZhi("中国", "湖南", "湘潭市", "湘潭县云湖桥镇北岸村道林组83号")
        danwei = DanWei("任之堂")
        yisheng = YiSheng('余浩', 1, date(2015, 4, 2), '13673265859')
        danwei.yishengs = [yisheng]
        danwei.dizhi = dizhi
        Session.add(danwei)
        Session.commit()
        items = Session.query(DanWei).filter(DanWei.mingcheng == "任之堂").first()
        self.assertEqual(items.dizhi.jiedao, u"湘潭县云湖桥镇北岸村道林组83号")

        items = Session.query(YiSheng).join(DanWei).filter(
            DanWei.mingcheng == "任之堂").first()
        self.assertEqual(items.danwei.dizhi.jiedao, u"湘潭县云湖桥镇北岸村道林组83号")
        self.assertEqual(items.danwei.yishengs[0], items)

        items = Session.query(DanWei).all()
        items.extend(Session.query(DiZhi).all())
        items.extend(Session.query(YiSheng).all())

        for m in items:
            Session.delete(m)
        Session.commit()
예제 #30
0
파일: dataset.py 프로젝트: vmartinv/cms-oia
class AddTestcaseHandler(BaseHandler):
    """Add a testcase to a dataset.

    """
    @require_permission(BaseHandler.PERMISSION_ALL)
    def get(self, dataset_id):
        dataset = self.safe_get_item(Dataset, dataset_id)
        task = dataset.task

        self.r_params = self.render_params()
        self.r_params["task"] = task
        self.r_params["dataset"] = dataset
        self.render("add_testcase.html", **self.r_params)

    @require_permission(BaseHandler.PERMISSION_ALL)
    def post(self, dataset_id):
        fallback_page = "/dataset/%s/testcases/add" % dataset_id

        dataset = self.safe_get_item(Dataset, dataset_id)
        task = dataset.task

        codename = self.get_argument("codename")

        try:
            input_ = self.request.files["input"][0]
            output = self.request.files["output"][0]
        except KeyError:
            self.application.service.add_notification(
                make_datetime(), "Invalid data",
                "Please fill both input and output.")
            self.redirect(fallback_page)
            return

        public = self.get_argument("public", None) is not None
        task_name = task.name
        self.sql_session.close()

        try:
            input_digest = \
                self.application.service.file_cacher.put_file_content(
                    input_["body"],
                    "Testcase input for task %s" % task_name)
            output_digest = \
                self.application.service.file_cacher.put_file_content(
                    output["body"],
                    "Testcase output for task %s" % task_name)
        except Exception as error:
            self.application.service.add_notification(
                make_datetime(), "Testcase storage failed", repr(error))
            self.redirect(fallback_page)
            return

        self.sql_session = Session()
        dataset = self.safe_get_item(Dataset, dataset_id)
        task = dataset.task

        testcase = Testcase(codename,
                            public,
                            input_digest,
                            output_digest,
                            dataset=dataset)
        self.sql_session.add(testcase)

        if self.try_commit():
            # max_score and/or extra_headers might have changed.
            self.application.service.proxy_service.reinitialize()
            self.redirect("/task/%s" % task.id)
        else:
            self.redirect(fallback_page)
예제 #31
0
 def __init__(self, announcement):
     self.announcement = announcement
     super(MyAnnouncement, self).\
         __init__(Session.object_session(self.announcement))
예제 #32
0
 def setUp(self):
     self.session = Session()
예제 #33
0
class TestCaseWithDatabase(unittest.TestCase):
    """TestCase subclass starting with a clean testing database."""
    @classmethod
    def setUpClass(cls):
        assert "fortesting" in str(cms.db.engine), \
            "Monkey patching of DB connection string failed"
        drop_db()
        init_db()
        cls.connection = cms.db.engine.connect()
        cms.db.metadata.create_all(cls.connection)

    @classmethod
    def tearDownClass(cls):
        drop_db()
        cls.connection.close()
        cms.db.engine.dispose()

    def setUp(self):
        self.session = Session()

    def tearDown(self):
        self.session.rollback()

    def delete_data(self):
        """Delete all the data in the DB.

        This is useful to call during tear down, for tests that rely on
        starting from a clean DB.

        """
        for table in itervalues(Base.metadata.tables):
            self.session.execute(table.delete())
        self.session.commit()

    @staticmethod
    def add_fsobject(digest, content):
        dbbackend = DBBackend()
        fobj = dbbackend.create_file(digest)
        fobj.write(content)
        dbbackend.commit_file(fobj, digest)

    @staticmethod
    def get_contest(**kwargs):
        """Create a contest"""
        args = {
            "name": unique_unicode_id(),
            "description": unique_unicode_id(),
        }
        args.update(kwargs)
        contest = Contest(**args)
        return contest

    def add_contest(self, **kwargs):
        """Create a contest and add it to the session"""
        contest = self.get_contest(**kwargs)
        self.session.add(contest)
        return contest

    @staticmethod
    def get_user(**kwargs):
        """Create a user"""
        args = {
            "username": unique_unicode_id(),
            "password": "",
            "first_name": unique_unicode_id(),
            "last_name": unique_unicode_id(),
        }
        args.update(kwargs)
        user = User(**args)
        return user

    def add_user(self, **kwargs):
        """Create a user and add it to the session"""
        user = self.get_user(**kwargs)
        self.session.add(user)
        return user

    @staticmethod
    def get_participation(user=None, contest=None, **kwargs):
        """Create a participation"""
        user = user if user is not None else TestCaseWithDatabase.get_user()
        contest = contest \
            if contest is not None else TestCaseWithDatabase.get_contest()
        args = {
            "user": user,
            "contest": contest,
        }
        args.update(kwargs)
        participation = Participation(**args)
        return participation

    def add_participation(self, **kwargs):
        """Create a participation and add it to the session"""
        participation = self.get_participation(**kwargs)
        self.session.add(participation)
        return participation

    @staticmethod
    def get_task(**kwargs):
        """Create a task"""
        args = {
            "name": unique_unicode_id(),
            "title": unique_unicode_id(),
        }
        args.update(kwargs)
        task = Task(**args)
        return task

    def add_task(self, **kwargs):
        """Create a task and add it to the session"""
        task = self.get_task(**kwargs)
        self.session.add(task)
        return task

    def add_statement(self, task=None, **kwargs):
        """Create a statement and add it to the session"""
        task = task if task is not None else self.add_task()
        args = {
            "task": task,
            "digest": unique_digest(),
            "language": unique_unicode_id(),
        }
        args.update(kwargs)
        statement = Statement(**args)
        self.session.add(statement)
        return statement

    @staticmethod
    def get_dataset(task=None, **kwargs):
        """Create a dataset"""
        task = task if task is not None else TestCaseWithDatabase.get_task()
        args = {
            "task": task,
            "description": unique_unicode_id(),
            "task_type": "",
            # "None" won't work here as the column is defined as non
            # nullable. As soon as we'll depend on SQLAlchemy 1.1 we
            # will be able to put JSON.NULL here instead.
            "task_type_parameters": {},
            "score_type": "",
            # Same here.
            "score_type_parameters": {},
        }
        args.update(kwargs)
        dataset = Dataset(**args)
        return dataset

    def add_dataset(self, **kwargs):
        """Create a dataset and add it to the session"""
        dataset = self.get_dataset(**kwargs)
        self.session.add(dataset)
        return dataset

    def add_testcase(self, dataset=None, **kwargs):
        """Add a testcase."""
        dataset = dataset if dataset is not None else self.add_dataset()
        args = {
            "dataset": dataset,
            "codename": unique_unicode_id(),
            "input": unique_digest(),
            "output": unique_digest(),
        }
        args.update(kwargs)
        testcase = Testcase(**args)
        self.session.add(testcase)
        return testcase

    def add_submission(self, task=None, participation=None, **kwargs):
        """Add a submission."""
        if task is None:
            task = self.add_task(contest=self.add_contest())
        participation = participation \
            if participation is not None \
            else self.add_participation(contest=task.contest)
        assert task.contest == participation.contest
        args = {
            "task": task,
            "participation": participation,
            "timestamp": (task.contest.start + timedelta(0, unique_long_id())),
        }
        args.update(kwargs)
        submission = Submission(**args)
        self.session.add(submission)
        return submission

    def add_file(self, submission=None, **kwargs):
        """Create a file and add it to the session"""
        if submission is None:
            submission = self.add_sbubmission()
        args = {
            "submission": submission,
            "filename": unique_unicode_id(),
            "digest": unique_digest(),
        }
        args.update(kwargs)
        file = File(**args)
        self.session.add(file)
        return file

    def add_submission_result(self, submission=None, dataset=None, **kwargs):
        """Add a submission result."""
        task = None
        task = submission.task if submission is not None else task
        task = dataset.task if dataset is not None else task
        submission = submission \
            if submission is not None else self.add_submission(task=task)
        dataset = dataset \
            if dataset is not None else self.add_dataset(task=task)
        assert submission.task == dataset.task
        args = {
            "submission": submission,
            "dataset": dataset,
        }
        args.update(kwargs)
        submission_result = SubmissionResult(**args)
        self.session.add(submission_result)
        return submission_result

    def add_executable(self, submission_result=None, **kwargs):
        """Create an executable and add it to the session"""
        submission_result = submission_result \
            if submission_result is not None \
            else self.add_submission_result()
        args = {
            "submission_result": submission_result,
            "digest": unique_digest(),
            "filename": unique_unicode_id(),
        }
        args.update(kwargs)
        executable = Executable(**args)
        self.session.add(executable)
        return executable

    def add_evaluation(self, submission_result=None, testcase=None, **kwargs):
        """Add an evaluation."""
        dataset = None
        dataset = submission_result.dataset \
            if submission_result is not None else dataset
        dataset = testcase.dataset if testcase is not None else dataset
        submission_result = submission_result \
            if submission_result is not None \
            else self.add_submission_result(dataset=dataset)
        testcase = testcase if testcase is not None else self.add_testcase()
        assert submission_result.dataset == testcase.dataset
        args = {
            "submission_result": submission_result,
            "testcase": testcase,
        }
        args.update(kwargs)
        evaluation = Evaluation(**args)
        self.session.add(evaluation)
        return evaluation

    def add_user_test(self, task=None, participation=None, **kwargs):
        """Add a user test."""
        if task is None:
            task = self.add_task(contest=self.add_contest())
        participation = participation \
            if participation is not None \
            else self.add_participation(contest=task.contest)
        assert task.contest == participation.contest
        args = {
            "task": task,
            "participation": participation,
            "input": unique_digest(),
            "timestamp": (task.contest.start + timedelta(0, unique_long_id())),
        }
        args.update(kwargs)
        user_test = UserTest(**args)
        self.session.add(user_test)
        return user_test

    def add_user_test_result(self, user_test=None, dataset=None, **kwargs):
        """Add a user test result."""
        task = None
        task = user_test.task if user_test is not None else task
        task = dataset.task if dataset is not None else task
        user_test = user_test \
            if user_test is not None else self.add_user_test(task=task)
        dataset = dataset \
            if dataset is not None else self.add_dataset(task=task)
        assert user_test.task == dataset.task
        args = {
            "user_test": user_test,
            "dataset": dataset,
        }
        args.update(kwargs)
        user_test_result = UserTestResult(**args)
        self.session.add(user_test_result)
        return user_test_result

    # Other commonly used generation functions.

    def add_submission_with_results(self,
                                    task,
                                    participation,
                                    compilation_outcome=None):
        """Add a submission for the tasks, all of its results, and optionally
        the compilation outcome for all results.

        """
        submission = self.add_submission(task, participation)
        results = [
            self.add_submission_result(submission, dataset)
            for dataset in task.datasets
        ]
        if compilation_outcome is not None:
            for result in results:
                result.set_compilation_outcome(compilation_outcome)
        return submission, results

    def add_user_test_with_results(self, compilation_outcome=None):
        """Add a user_test for the first tasks, all of its results, and
        optionally the compilation outcome for all results.

        """
        user_test = self.add_user_test(self.tasks[0], self.participation)
        results = [
            self.add_user_test_result(user_test, dataset)
            for dataset in self.tasks[0].datasets
        ]
        if compilation_outcome is not None:
            for result in results:
                result.set_compilation_outcome(compilation_outcome)
        return user_test, results

    @staticmethod
    def get_team(**kwargs):
        """Create a team"""
        args = {
            "code": unique_unicode_id(),
            "name": unique_unicode_id(),
        }
        args.update(kwargs)
        team = Team(**args)
        return team

    def add_team(self, **kwargs):
        """Create a team and add it to the session"""
        team = self.get_team(**kwargs)
        self.session.add(team)
        return team
예제 #34
0
class TestCaseWithDatabase(unittest.TestCase):
    """TestCase subclass starting with a clean testing database."""

    @classmethod
    def setUpClass(cls):
        cms.db.engine = create_engine(cms.config.database)
        drop_db()
        init_db()
        cls.connection = cms.db.engine.connect()
        cms.db.metadata.create_all(cls.connection)

    @classmethod
    def tearDownClass(cls):
        drop_db()
        cls.connection.close()
        cms.db.engine.dispose()

    def setUp(self):
        self.session = Session()

    def tearDown(self):
        self.session.rollback()

    def add_contest(self, **kwargs):
        """Add a contest."""
        args = {
            "name": unique_unicode_id(),
            "description": unique_unicode_id(),
        }
        args.update(kwargs)
        contest = Contest(**args)
        self.session.add(contest)
        return contest

    def add_user(self, **kwargs):
        """Add a user."""
        args = {
            "username": unique_unicode_id(),
            "password": "",
            "first_name": unique_unicode_id(),
            "last_name": unique_unicode_id(),
        }
        args.update(kwargs)
        user = User(**args)
        self.session.add(user)
        return user

    def add_participation(self, user=None, contest=None, **kwargs):
        """Add a participation."""
        user = user if user is not None else self.add_user()
        contest = contest if contest is not None else self.add_contest()
        args = {
            "user": user,
            "contest": contest,
        }
        args.update(kwargs)
        participation = Participation(**args)
        self.session.add(participation)
        return participation

    def add_task(self, contest=None, **kwargs):
        """Add a task."""
        contest = contest if contest is not None else self.add_contest()
        args = {
            "contest": contest,
            "name": unique_unicode_id(),
            "title": unique_unicode_id(),
        }
        args.update(kwargs)
        task = Task(**args)
        self.session.add(task)
        return task

    def add_dataset(self, task=None, **kwargs):
        """Add a dataset."""
        task = task if task is not None else self.add_task()
        args = {
            "task": task,
            "description": unique_unicode_id(),
            "task_type": "",
            "task_type_parameters": "",
            "score_type": "",
            "score_type_parameters": "",
        }
        args.update(kwargs)
        dataset = Dataset(**args)
        self.session.add(dataset)
        return dataset

    def add_testcase(self, dataset=None, **kwargs):
        """Add a testcase."""
        dataset = dataset if dataset is not None else self.add_dataset()
        args = {
            "dataset": dataset,
            "codename": unique_unicode_id(),
            "input": unique_digest(),
            "output": unique_digest(),
        }
        args.update(kwargs)
        testcase = Testcase(**args)
        self.session.add(testcase)
        return testcase

    def add_submission(self, task=None, participation=None, **kwargs):
        """Add a submission."""
        task = task if task is not None else self.add_task()
        participation = participation \
            if participation is not None \
            else self.add_participation(contest=task.contest)
        assert task.contest == participation.contest
        args = {
            "task": task,
            "participation": participation,
            "timestamp": (task.contest.start + timedelta(0, unique_long_id())),
        }
        args.update(kwargs)
        submission = Submission(**args)
        self.session.add(submission)
        return submission

    def add_submission_result(self, submission=None, dataset=None, **kwargs):
        """Add a submission result."""
        task = None
        task = submission.task if submission is not None else task
        task = dataset.task if dataset is not None else task
        submission = submission \
            if submission is not None else self.add_submission(task=task)
        dataset = dataset \
            if dataset is not None else self.add_dataset(task=task)
        assert submission.task == dataset.task
        args = {
            "submission": submission,
            "dataset": dataset,
        }
        args.update(kwargs)
        submission_result = SubmissionResult(**args)
        self.session.add(submission_result)
        return submission_result

    def add_evaluation(self, submission_result=None, testcase=None, **kwargs):
        """Add an evaluation."""
        dataset = None
        dataset = submission_result.dataset \
            if submission_result is not None else dataset
        dataset = testcase.dataset if testcase is not None else dataset
        submission_result = submission_result \
            if submission_result is not None else self.add_submission_result()
        testcase = testcase if testcase is not None else self.add_testcase()
        assert submission_result.dataset == testcase.dataset
        args = {
            "submission_result": submission_result,
            "testcase": testcase,
        }
        args.update(kwargs)
        evaluation = Evaluation(**args)
        self.session.add(evaluation)
        return evaluation

    def add_user_test(self, task=None, participation=None, **kwargs):
        """Add a user test."""
        task = task if task is not None else self.add_task()
        participation = participation \
            if participation is not None \
            else self.add_participation(contest=task.contest)
        assert task.contest == participation.contest
        args = {
            "task": task,
            "participation": participation,
            "input": unique_digest(),
            "timestamp": (task.contest.start + timedelta(0, unique_long_id())),
        }
        args.update(kwargs)
        user_test = UserTest(**args)
        self.session.add(user_test)
        return user_test

    def add_user_test_result(self, user_test=None, dataset=None, **kwargs):
        """Add a user test result."""
        task = None
        task = user_test.task if user_test is not None else task
        task = dataset.task if dataset is not None else task
        user_test = user_test \
            if user_test is not None else self.add_user_test(task=task)
        dataset = dataset \
            if dataset is not None else self.add_dataset(task=task)
        assert user_test.task == dataset.task
        args = {
            "user_test": user_test,
            "dataset": dataset,
        }
        args.update(kwargs)
        user_test_result = UserTestResult(**args)
        self.session.add(user_test_result)
        return user_test_result

    # Other commonly used generation functions.

    def add_submission_with_results(self, task, participation,
                                    compilation_outcome=None):
        """Add a submission for the tasks, all of its results, and optionally
        the compilation outcome for all results.

        """
        submission = self.add_submission(task, participation)
        results = [self.add_submission_result(submission, dataset)
                   for dataset in task.datasets]
        if compilation_outcome is not None:
            for result in results:
                result.set_compilation_outcome(compilation_outcome)
        return submission, results

    def add_user_test_with_results(self, compilation_outcome=None):
        """Add a user_test for the first tasks, all of its results, and
        optionally the compilation outcome for all results.

        """
        user_test = self.add_user_test(self.tasks[0], self.participation)
        results = [self.add_user_test_result(user_test, dataset)
                   for dataset in self.tasks[0].datasets]
        if compilation_outcome is not None:
            for result in results:
                result.set_compilation_outcome(compilation_outcome)
        return user_test, results
예제 #35
0
class BaseHandler(CommonRequestHandler):
    """Base RequestHandler for this application.

    All the RequestHandler classes in this application should be a
    child of this class.

    """

    # Whether the login cookie duration has to be refreshed when
    # this handler is called. Useful to filter asynchronous
    # requests.
    refresh_cookie = True

    def __init__(self, *args, **kwargs):
        super(BaseHandler, self).__init__(*args, **kwargs)
        self.timestamp = None
        self.cookie_lang = None
        self.browser_lang = None
        self.langs = None
        self._ = None

    def prepare(self):
        """This method is executed at the beginning of each request.

        """
        self.timestamp = make_datetime()

        self.set_header("Cache-Control", "no-cache, must-revalidate")

        self.sql_session = Session()
        self.contest = Contest.get_from_id(self.application.service.contest,
                                           self.sql_session)

        self._ = self.locale.translate

        self.r_params = self.render_params()

    def get_current_user(self):
        """The name is get_current_user because tornado wants it that
        way, but this is really a get_current_participation.

        Gets the current participation from cookies.

        If a valid cookie is retrieved, return a Participation tuple
        (specifically: the Participation involving the username
        specified in the cookie and the current contest).

        Otherwise (e.g. the user exists but doesn't participate in the
        current contest), return None.

        """
        remote_ip = self.request.remote_ip
        if self.contest.ip_autologin:
            self.clear_cookie("login")
            participations = self.sql_session.query(Participation)\
                .filter(Participation.contest == self.contest)\
                .filter(Participation.ip == remote_ip)\
                .all()
            if len(participations) == 1:
                return participations[0]

            if len(participations) > 1:
                logger.error("Multiple users have IP %s." % (remote_ip))
            else:
                logger.error("No user has IP %s" % (remote_ip))

            # If IP autologin is set, we do not allow password logins.
            return None

        if self.get_secure_cookie("login") is None:
            return None

        # Parse cookie.
        try:
            cookie = pickle.loads(self.get_secure_cookie("login"))
            username = cookie[0]
            password = cookie[1]
            last_update = make_datetime(cookie[2])
        except:
            self.clear_cookie("login")
            return None

        # Check if the cookie is expired.
        if self.timestamp - last_update > \
                timedelta(seconds=config.cookie_duration):
            self.clear_cookie("login")
            return None

        # Load user from DB.
        user = self.sql_session.query(User)\
            .filter(User.username == username)\
            .first()

        # Check if user exists.
        if user is None:
            self.clear_cookie("login")
            return None

        # Load participation from DB.
        participation = self.sql_session.query(Participation)\
            .filter(Participation.contest == self.contest)\
            .filter(Participation.user == user)\
            .first()

        # Check if participaton exists.
        if participation is None:
            self.clear_cookie("login")
            return None

        # If a contest-specific password is defined, use that. If it's
        # not, use the user's main password.
        if participation.password is None:
            correct_password = user.password
        else:
            correct_password = participation.password

        # Check if user is allowed to login.
        if password != correct_password:
            self.clear_cookie("login")
            return None

        # Check if user is using the right IP (or is on the right subnet)
        if self.contest.ip_restriction and participation.ip is not None \
                and not check_ip(self.request.remote_ip, participation.ip):
            self.clear_cookie("login")
            return None

        # Check if user is hidden
        if participation.hidden and self.contest.block_hidden_participations:
            self.clear_cookie("login")
            return None

        if self.refresh_cookie:
            self.set_secure_cookie("login",
                                   pickle.dumps((user.username,
                                                 password,
                                                 make_timestamp())),
                                   expires_days=None)

        return participation

    def get_user_locale(self):
        self.langs = self.application.service.langs
        lang_codes = self.langs.keys()

        if len(self.contest.allowed_localizations) > 0:
            lang_codes = filter_language_codes(
                lang_codes, self.contest.allowed_localizations)

        # TODO We fallback on "en" if no language matches: we could
        # return 406 Not Acceptable instead.
        # Select the one the user likes most.
        http_langs = [lang_code.replace("_", "-") for lang_code in lang_codes]
        self.browser_lang = parse_accept_header(
            self.request.headers.get("Accept-Language", ""),
            LanguageAccept).best_match(http_langs, "en")

        self.cookie_lang = self.get_cookie("language", None)

        if self.cookie_lang in http_langs:
            lang_code = self.cookie_lang
        else:
            lang_code = self.browser_lang

        self.set_header("Content-Language", lang_code)
        return self.langs[lang_code.replace("-", "_")]

    @staticmethod
    def _get_token_status(obj):
        """Return the status of the tokens for the given object.

        obj (Contest or Task): an object that has the token_* attributes.
        return (int): one of 0 (disabled), 1 (enabled/finite) and 2
                      (enabled/infinite).

        """
        if obj.token_mode == "disabled":
            return 0
        elif obj.token_mode == "finite":
            return 1
        elif obj.token_mode == "infinite":
            return 2
        else:
            raise RuntimeError("Unknown token_mode value.")

    def render_params(self):
        """Return the default render params used by almost all handlers.

        return (dict): default render params

        """
        ret = {}
        ret["timestamp"] = self.timestamp
        ret["contest"] = self.contest
        ret["url_root"] = get_url_root(self.request.path)

        ret["phase"] = self.contest.phase(self.timestamp)

        ret["printing_enabled"] = (config.printer is not None)

        if self.current_user is not None:
            participation = self.current_user

            res = compute_actual_phase(
                self.timestamp, self.contest.start, self.contest.stop,
                self.contest.per_user_time, participation.starting_time,
                participation.delay_time, participation.extra_time)

            ret["actual_phase"], ret["current_phase_begin"], \
                ret["current_phase_end"], ret["valid_phase_begin"], \
                ret["valid_phase_end"] = res

            if ret["actual_phase"] == 0:
                ret["phase"] = 0

            # set the timezone used to format timestamps
            ret["timezone"] = get_timezone(participation.user, self.contest)

        # some information about token configuration
        ret["tokens_contest"] = self._get_token_status(self.contest)

        t_tokens = sum(self._get_token_status(t) for t in self.contest.tasks)
        if t_tokens == 0:
            ret["tokens_tasks"] = 0  # all disabled
        elif t_tokens == 2 * len(self.contest.tasks):
            ret["tokens_tasks"] = 2  # all infinite
        else:
            ret["tokens_tasks"] = 1  # all finite or mixed

        # TODO Now all language names are shown in the active language.
        # It would be better to show them in the corresponding one.
        ret["lang_names"] = {}
        for lang_code, trans in self.langs.iteritems():
            language_name = None
            try:
                language_name = translate_language_country_code(
                    lang_code, trans)
            except ValueError:
                language_name = translate_language_code(
                    lang_code, trans)
            ret["lang_names"][lang_code.replace("_", "-")] = language_name

        ret["cookie_lang"] = self.cookie_lang
        ret["browser_lang"] = self.browser_lang

        return ret

    def finish(self, *args, **kwds):
        """Finish this response, ending the HTTP request.

        We override this method in order to properly close the database.

        TODO - Now that we have greenlet support, this method could be
        refactored in terms of context manager or something like
        that. So far I'm leaving it to minimize changes.

        """
        if hasattr(self, "sql_session"):
            try:
                self.sql_session.close()
            except Exception as error:
                logger.warning("Couldn't close SQL connection: %r", error)
        try:
            tornado.web.RequestHandler.finish(self, *args, **kwds)
        except IOError:
            # When the client closes the connection before we reply,
            # Tornado raises an IOError exception, that would pollute
            # our log with unnecessarily critical messages
            logger.debug("Connection closed before our reply.")

    def write_error(self, status_code, **kwargs):
        if "exc_info" in kwargs and \
                kwargs["exc_info"][0] != tornado.web.HTTPError:
            exc_info = kwargs["exc_info"]
            logger.error(
                "Uncaught exception (%r) while processing a request: %s",
                exc_info[1], ''.join(traceback.format_exception(*exc_info)))

        # We assume that if r_params is defined then we have at least
        # the data we need to display a basic template with the error
        # information. If r_params is not defined (i.e. something went
        # *really* bad) we simply return a basic textual error notice.
        if hasattr(self, 'r_params'):
            self.render("error.html", status_code=status_code, **self.r_params)
        else:
            self.write("A critical error has occurred :-(")
            self.finish()
예제 #36
0
    def post(self, dataset_id):
        fallback_page = "/dataset/%s/testcases/add_multiple" % dataset_id

        # TODO: this method is quite long, some splitting is needed.
        dataset = self.safe_get_item(Dataset, dataset_id)
        task = dataset.task

        try:
            archive = self.request.files["archive"][0]
        except KeyError:
            self.application.service.add_notification(
                make_datetime(), "Invalid data",
                "Please choose tests archive.")
            self.redirect(fallback_page)
            return

        public = self.get_argument("public", None) is not None
        overwrite = self.get_argument("overwrite", None) is not None

        # Get input/output file names templates, or use default ones.
        input_template = self.get_argument("input_template", None)
        if not input_template:
            input_template = "input.*"
        output_template = self.get_argument("output_template", None)
        if not output_template:
            output_template = "output.*"
        input_re = re.compile(
            re.escape(input_template).replace("\\*", "(.*)") + "$")
        output_re = re.compile(
            re.escape(output_template).replace("\\*", "(.*)") + "$")

        task_name = task.name
        self.sql_session.close()

        fp = StringIO(archive["body"])
        try:
            with zipfile.ZipFile(fp, "r") as archive_zfp:
                tests = dict()
                # Match input/output file names to testcases' codenames.
                for filename in archive_zfp.namelist():
                    match = input_re.match(filename)
                    if match:
                        codename = match.group(1)
                        if codename not in tests:
                            tests[codename] = [None, None]
                        tests[codename][0] = filename
                    else:
                        match = output_re.match(filename)
                        if match:
                            codename = match.group(1)
                            if codename not in tests:
                                tests[codename] = [None, None]
                            tests[codename][1] = filename

                skipped_tc = []
                overwritten_tc = []
                added_tc = []
                for codename, testdata in tests.iteritems():
                    # If input or output file isn't found, skip it.
                    if not testdata[0] or not testdata[1]:
                        continue
                    self.sql_session = Session()

                    # Check, whether current testcase already exists.
                    dataset = self.safe_get_item(Dataset, dataset_id)
                    task = dataset.task
                    if codename in dataset.testcases:
                        # If we are allowed, remove existing testcase.
                        # If not - skip this testcase.
                        if overwrite:
                            testcase = dataset.testcases[codename]
                            self.sql_session.delete(testcase)

                            if not self.try_commit():
                                skipped_tc.append(codename)
                                continue
                            overwritten_tc.append(codename)
                        else:
                            skipped_tc.append(codename)
                            continue

                    # Add current testcase.
                    try:
                        input_ = archive_zfp.read(testdata[0])
                        output = archive_zfp.read(testdata[1])
                    except Exception as error:
                        self.application.service.add_notification(
                            make_datetime(),
                            "Reading testcase %s failed" % codename,
                            repr(error))
                        self.redirect(fallback_page)
                        return
                    try:
                        input_digest = self.application.service\
                            .file_cacher.put_file_content(
                                input_,
                                "Testcase input for task %s" % task_name)
                        output_digest = self.application.service\
                            .file_cacher.put_file_content(
                                output,
                                "Testcase output for task %s" % task_name)
                    except Exception as error:
                        self.application.service.add_notification(
                            make_datetime(), "Testcase storage failed",
                            repr(error))
                        self.redirect(fallback_page)
                        return
                    testcase = Testcase(codename,
                                        public,
                                        input_digest,
                                        output_digest,
                                        dataset=dataset)
                    self.sql_session.add(testcase)

                    if not self.try_commit():
                        self.application.service.add_notification(
                            make_datetime(), "Couldn't add test %s" % codename,
                            "")
                        self.redirect(fallback_page)
                        return
                    if codename not in overwritten_tc:
                        added_tc.append(codename)
        except zipfile.BadZipfile:
            self.application.service.add_notification(
                make_datetime(), "The selected file is not a zip file.",
                "Please select a valid zip file.")
            self.redirect(fallback_page)
            return

        self.application.service.add_notification(
            make_datetime(),
            "Successfully added %d and overwritten %d testcase(s)" %
            (len(added_tc), len(overwritten_tc)),
            "Added: %s; overwritten: %s; skipped: %s" %
            (", ".join(added_tc) if added_tc else "none",
             ", ".join(overwritten_tc) if overwritten_tc else "none",
             ", ".join(skipped_tc) if skipped_tc else "none"))
        self.application.service.proxy_service.reinitialize()
        self.redirect("/task/%s" % task.id)
예제 #37
0
 def setUp(self):
     super().setUp()
     self.session = Session()
예제 #38
0
 def __init__(self, question):
     self.question = question
     super(MyQuestion, self).__init__(Session.object_session(self.question))
예제 #39
0
파일: base.py 프로젝트: giomasce/cms
class BaseHandler(CommonRequestHandler):
    """Base RequestHandler for this application.

    All the RequestHandler classes in this application should be a
    child of this class.

    """
    def try_commit(self):
        """Try to commit the current session.

        If not successful display a warning in the webpage.

        return (bool): True if commit was successful, False otherwise.

        """
        try:
            self.sql_session.commit()
        except IntegrityError as error:
            self.application.service.add_notification(make_datetime(),
                                                      "Operation failed.",
                                                      "%s" % error)
            return False
        else:
            self.application.service.add_notification(make_datetime(),
                                                      "Operation successful.",
                                                      "")
            return True

    def safe_get_item(self, cls, ident, session=None):
        """Get item from database of class cls and id ident, using
        session if given, or self.sql_session if not given. If id is
        not found, raise a 404.

        cls (type): class of object to retrieve.
        ident (string): id of object.
        session (Session|None): session to use.

        return (object): the object with the given id.

        raise (HTTPError): 404 if not found.

        """
        if session is None:
            session = self.sql_session
        entity = cls.get_from_id(ident, session)
        if entity is None:
            raise tornado.web.HTTPError(404)
        return entity

    def prepare(self):
        """This method is executed at the beginning of each request.

        """
        # Attempt to update the contest and all its references
        # If this fails, the request terminates.
        self.set_header("Cache-Control", "no-cache, must-revalidate")

        self.sql_session = Session()
        self.sql_session.expire_all()
        self.contest = None

    def render_params(self):
        """Return the default render params used by almost all handlers.

        return (dict): default render params

        """
        params = {}
        params["timestamp"] = make_datetime()
        params["contest"] = self.contest
        params["url_root"] = get_url_root(self.request.path)
        if self.contest is not None:
            params["phase"] = self.contest.phase(params["timestamp"])
            # Keep "== None" in filter arguments. SQLAlchemy does not
            # understand "is None".
            params["unanswered"] = self.sql_session.query(Question)\
                .join(Participation)\
                .filter(Participation.contest_id == self.contest.id)\
                .filter(Question.reply_timestamp == None)\
                .filter(Question.ignored == False)\
                .count()  # noqa
        # TODO: not all pages require all these data.
        params["contest_list"] = self.sql_session.query(Contest).all()
        params["task_list"] = self.sql_session.query(Task).all()
        params["user_list"] = self.sql_session.query(User).all()
        params["team_list"] = self.sql_session.query(Team).all()
        return params

    def finish(self, *args, **kwds):
        """Finish this response, ending the HTTP request.

        We override this method in order to properly close the database.

        TODO - Now that we have greenlet support, this method could be
        refactored in terms of context manager or something like
        that. So far I'm leaving it to minimize changes.

        """
        self.sql_session.close()
        try:
            tornado.web.RequestHandler.finish(self, *args, **kwds)
        except IOError:
            # When the client closes the connection before we reply,
            # Tornado raises an IOError exception, that would pollute
            # our log with unnecessarily critical messages
            logger.debug("Connection closed before our reply.")

    def write_error(self, status_code, **kwargs):
        if "exc_info" in kwargs and \
                kwargs["exc_info"][0] != tornado.web.HTTPError:
            exc_info = kwargs["exc_info"]
            logger.error(
                "Uncaught exception (%r) while processing a request: %s",
                exc_info[1], ''.join(traceback.format_exception(*exc_info)))

        # Most of the handlers raise a 404 HTTP error before r_params
        # is defined. If r_params is not defined we try to define it
        # here, and if it fails we simply return a basic textual error notice.
        if self.r_params is None:
            try:
                self.r_params = self.render_params()
            except:
                self.write("A critical error has occurred :-(")
                self.finish()
                return
        self.render("error.html", status_code=status_code, **self.r_params)

    get_string = argument_reader(lambda a: a, empty="")

    # When a checkbox isn't active it's not sent at all, making it
    # impossible to distinguish between missing and False.
    def get_bool(self, dest, name):
        """Parse a boolean.

        dest (dict): a place to store the result.
        name (string): the name of the argument and of the item.

        """
        value = self.get_argument(name, False)
        try:
            dest[name] = bool(value)
        except:
            raise ValueError("Can't cast %s to bool." % value)

    get_int = argument_reader(parse_int)

    get_timedelta_sec = argument_reader(parse_timedelta_sec)

    get_timedelta_min = argument_reader(parse_timedelta_min)

    get_datetime = argument_reader(parse_datetime)

    get_ip_address_or_subnet = argument_reader(parse_ip_address_or_subnet)

    def get_submission_format(self, dest):
        """Parse the submission format.

        Using the two arguments "submission_format_choice" and
        "submission_format" set the "submission_format" item of the
        given dictionary.

        dest (dict): a place to store the result.

        """
        choice = self.get_argument("submission_format_choice", "other")
        if choice == "simple":
            filename = "%s.%%l" % dest["name"]
            format_ = [SubmissionFormatElement(filename)]
        elif choice == "other":
            value = self.get_argument("submission_format", "[]")
            if value == "":
                value = "[]"
            format_ = []
            try:
                for filename in json.loads(value):
                    format_ += [SubmissionFormatElement(filename)]
            except ValueError:
                raise ValueError("Submission format not recognized.")
        else:
            raise ValueError("Submission format not recognized.")
        dest["submission_format"] = format_

    def get_time_limit(self, dest, field):
        """Parse the time limit.

        Read the argument with the given name and use its value to set
        the "time_limit" item of the given dictionary.

        dest (dict): a place to store the result.
        field (string): the name of the argument to use.

        """
        value = self.get_argument(field, None)
        if value is None:
            return
        if value == "":
            dest["time_limit"] = None
        else:
            try:
                value = float(value)
            except:
                raise ValueError("Can't cast %s to float." % value)
            if not 0 <= value < float("+inf"):
                raise ValueError("Time limit out of range.")
            dest["time_limit"] = value

    def get_memory_limit(self, dest, field):
        """Parse the memory limit.

        Read the argument with the given name and use its value to set
        the "memory_limit" item of the given dictionary.

        dest (dict): a place to store the result.
        field (string): the name of the argument to use.

        """
        value = self.get_argument(field, None)
        if value is None:
            return
        if value == "":
            dest["memory_limit"] = None
        else:
            try:
                value = int(value)
            except:
                raise ValueError("Can't cast %s to float." % value)
            if not 0 < value:
                raise ValueError("Invalid memory limit.")
            dest["memory_limit"] = value

    def get_task_type(self, dest, name, params):
        """Parse the task type.

        Parse the arguments to get the task type and its parameters,
        and fill them in the "task_type" and "task_type_parameters"
        items of the given dictionary.

        dest (dict): a place to store the result.
        name (string): the name of the argument that holds the task
            type name.
        params (string): the prefix of the names of the arguments that
            hold the parameters.

        """
        name = self.get_argument(name, None)
        if name is None:
            raise ValueError("Task type not found.")
        try:
            class_ = get_task_type_class(name)
        except KeyError:
            raise ValueError("Task type not recognized: %s." % name)
        params = json.dumps(class_.parse_handler(self, params + name + "_"))
        dest["task_type"] = name
        dest["task_type_parameters"] = params

    def get_score_type(self, dest, name, params):
        """Parse the score type.

        Parse the arguments to get the score type and its parameters,
        and fill them in the "score_type" and "score_type_parameters"
        items of the given dictionary.

        dest (dict): a place to store the result.
        name (string): the name of the argument that holds the score
            type name.
        params (string): the name of the argument that hold the
            parameters.

        """
        name = self.get_argument(name, None)
        if name is None:
            raise ValueError("Score type not found.")
        try:
            get_score_type_class(name)
        except KeyError:
            raise ValueError("Score type not recognized: %s." % name)
        params = self.get_argument(params, None)
        if params is None:
            raise ValueError("Score type parameters not found.")
        dest["score_type"] = name
        dest["score_type_parameters"] = params

    def render_params_for_submissions(self, query, page, page_size=50):
        """Add data about the requested submissions to r_params.

        submission_query (sqlalchemy.orm.query.Query): the query
            giving back all interesting submissions.
        page (int): the index of the page to display.
        page_size(int): the number of submissions per page.

        """
        query = query\
            .options(joinedload(Submission.task))\
            .options(joinedload(Submission.participation))\
            .options(joinedload(Submission.files))\
            .options(joinedload(Submission.token))\
            .options(joinedload(Submission.results)
                     .joinedload(SubmissionResult.evaluations))\
            .order_by(Submission.timestamp.desc())

        offset = page * page_size
        count = query.count()

        if self.r_params is None:
            self.r_params = self.render_params()

        # A page showing paginated submissions can use these
        # parameters: total number of submissions, submissions to
        # display in this page, index of the current page, total
        # number of pages.
        self.r_params["submission_count"] = count
        self.r_params["submissions"] = \
            query.slice(offset, offset + page_size).all()
        self.r_params["submission_page"] = page
        self.r_params["submission_pages"] = \
            (count + page_size - 1) // page_size