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
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)
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)
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
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
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)
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()
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)
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)
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)
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()
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)
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)
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)
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 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)
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)
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()
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()
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")
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()
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()
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()
def setUp(self): super(DatabaseMixin, self).setUp() self.session = Session()
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
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 """
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)
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()
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)
def __init__(self, announcement): self.announcement = announcement super(MyAnnouncement, self).\ __init__(Session.object_session(self.announcement))
def setUp(self): self.session = Session()
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
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
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()
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)
def setUp(self): super().setUp() self.session = Session()
def __init__(self, question): self.question = question super(MyQuestion, self).__init__(Session.object_session(self.question))
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