diff --git a/backstage.py b/backstage.py index 81cc427..9757ee3 100644 --- a/backstage.py +++ b/backstage.py @@ -2,11 +2,12 @@ # AUTHOR: Zeray Rice # FILE: backstage.py # CREATED: 02:43:49 15/03/2012 -# MODIFIED: 03:31:00 18/04/2012 +# MODIFIED: 18:31:05 18/04/2012 import re import datetime import functools +from sqlalchemy.orm.exc import NoResultFound from tornado.web import HTTPError @@ -174,10 +175,14 @@ def post(self): error.extend(self.check_text_value(name, self._("Name"), required = True, max = 100)) error.extend(self.check_text_value(link, self._("Link"), required = True, max = 100)) if not error: - duplinode = self.select_node_by_link(link) - if duplinode: + try: + duplinode = self.select_node_by_link(link) + except NoResultFound: + pass + else: error.append(self._("This link have taken.")) - node.id = nid + if nid: + node.id = nid node.name = name node.link = link node.description = "" diff --git a/forum.py b/forum.py index 9754585..302e424 100644 --- a/forum.py +++ b/forum.py @@ -2,11 +2,12 @@ # AUTHOR: Zeray Rice # FILE: forum.py # CREATED: 22:39:44 17/04/2012 -# MODIFIED: 18:21:14 18/04/2012 +# MODIFIED: 18:52:37 18/04/2012 import datetime from tornado.web import HTTPError from tornado.web import authenticated +from sqlalchemy.orm.exc import NoResultFound from judge.db import Node from judge.db import Reply @@ -57,6 +58,7 @@ def get(self, link): node = self.select_node_by_link(link.lower()) if not node: raise HTTPError(404) + topic = None if self.current_user.admin: tid = self.get_argument("tid", default = 0) try: @@ -73,8 +75,9 @@ def get(self, link): self.render("topic_create.html", locals()) @authenticated def post(self, link): - node = self.select_node_by_link(link.lower()) - if not node: + try: + node = self.select_node_by_link(link.lower()) + except NoResultFound: raise HTTPError(404) title = self.get_argument("title", default = "") content = self.get_argument("content", default = "") @@ -157,7 +160,7 @@ def post(self, topic_id): self.render("topic.html", locals()) return reply = Reply() - reply.content = content + reply.content = self.xhtml_escape(content) reply.topic_id = topic.id reply.member_id = self.current_user.id reply.create = datetime.datetime.now() diff --git a/handlers.py b/handlers.py index b199cf0..e861379 100644 --- a/handlers.py +++ b/handlers.py @@ -2,7 +2,7 @@ # AUTHOR: Zeray Rice # FILE: handlers.py # CREATED: 01:41:06 08/03/2012 -# MODIFIED: 18:18:55 18/04/2012 +# MODIFIED: 20:28:26 18/04/2012 # DESCRIPTION: URL Route from api import * @@ -44,5 +44,6 @@ (r'/t/([\d]*)', ViewTopicHandler), (r'/new/(.*)', CreateTopicHandler), (r'/forum', ViewForumHandler), + (r'/test', TestHandler), (r'/api/problem/get/([\d]*)', GetProblemHandler), ] diff --git a/home.py b/home.py index 5612cb0..f3ab41b 100644 --- a/home.py +++ b/home.py @@ -2,17 +2,18 @@ # AUTHOR: Zeray Rice # FILE: home.py # CREATED: 02:00:16 08/03/2012 -# MODIFIED: 19:27:54 17/04/2012 +# MODIFIED: 18:26:17 18/04/2012 # DESCRIPTION: Home handler from contest import get_contest_status +from judge.db import ForumDBMixin from judge.db import MemberDBMixin from judge.db import ContestDBMixin from judge.db import ProblemDBMixin from judge.base import BaseHandler -class HomeHandler(BaseHandler, MemberDBMixin, ProblemDBMixin, ContestDBMixin): +class HomeHandler(BaseHandler, MemberDBMixin, ProblemDBMixin, ContestDBMixin, ForumDBMixin): def get(self): title = self._("Home") breadcrumb = [] @@ -23,6 +24,7 @@ def get(self): for contest in latest_contest: contest.status = get_contest_status(contest) latest_topic = [] + latest_node = self.select_latest_node() count_problem = self.count_visible_problem() count_member = self.count_member() self.render("home.html", locals()) diff --git a/judge/base/__init__.py b/judge/base/__init__.py index d1d05eb..c69715a 100644 --- a/judge/base/__init__.py +++ b/judge/base/__init__.py @@ -2,7 +2,7 @@ # AUTHOR: Zeray Rice # FILE: judge/base/__init__.py # CREATED: 01:49:33 08/03/2012 -# MODIFIED: 02:16:21 18/04/2012 +# MODIFIED: 22:24:01 18/04/2012 # DESCRIPTION: Base handler import re @@ -20,6 +20,7 @@ from pygments.lexers import CppLexer from pygments.lexers import DelphiLexer from pygments.formatters import HtmlFormatter +from sqlalchemy.orm.exc import NoResultFound import tornado.web import tornado.escape @@ -104,6 +105,7 @@ def render(self, tplname, args = {}): tpl = self.jinja2.get_template(tplname) ren = tpl.render(page = self, _ = self._, user = self.current_user, **args) self.write(ren) + self.db.close() self.finish() def write_error(self, status_code, **kwargs): '''Rewrite write_error for custom error page''' @@ -154,8 +156,11 @@ def check_username(self, usr, queryDB = False): regex = re.compile(r'^([\w\d]*)$'), \ regex_msg = self._("A username can only contain letters and digits."))) if not error and queryDB: - query = self.select_member_by_username_lower(usr.lower()) - if query: + try: + query = self.select_member_by_username_lower(usr.lower()) + except NoResultFound: + pass + else: error.append(self._("That username is taken. Please choose another.")) return error def check_password(self, pwd): @@ -166,8 +171,11 @@ def check_email(self, email, queryDB = False): regex = re.compile(r"(?:^|\s)[-a-z0-9_.+]+@(?:[-a-z0-9]+\.)+[a-z]{2,6}(?:\s|$)", re.IGNORECASE), \ regex_msg = self._("Your Email address is invalid."))) if not error and queryDB: - query = self.select_member_by_email(email) - if query: + try: + query = self.select_member_by_email(email) + except NoResultFound: + pass + else: error.append(self._("That Email is taken. Please choose another.")) return error def get_gravatar_url(self, email): @@ -178,8 +186,6 @@ def post_to_judger(self, query, judger, callback = None): query["code"] = query["code"].decode("utf-8") query = dict(sorted(query.iteritems(), key=itemgetter(1))) jsondump = json.dumps(query) - print jsondump - print judger.pubkey.strip() sign = hashlib.sha1(jsondump + judger.pubkey.strip()).hexdigest() query["sign"] = sign http_client = AsyncHTTPClient() diff --git a/judge/db/__init__.py b/judge/db/__init__.py index 2743b08..06d21cd 100644 --- a/judge/db/__init__.py +++ b/judge/db/__init__.py @@ -2,7 +2,7 @@ # AUTHOR: Zeray Rice # FILE: judge/db/__init__.py # CREATED: 02:01:23 08/03/2012 -# MODIFIED: 18:18:21 18/04/2012 +# MODIFIED: 20:41:50 18/04/2012 # DESCRIPTION: Database Table Object import uuid @@ -26,9 +26,9 @@ class MemberDBMixin(object): def count_member(self): return self.db.query(Member).count() def count_accepted_by_member_id(self, member_id): - return self.db.query(Submit).filter_by(member_id = 1).filter_by(status = 1).count() + return self.db.query(Submit).filter_by(member_id = member_id).filter_by(status = 1).count() def count_submit_by_member_id(self, member_id): - return self.db.query(Submit).filter_by(member_id = 1).count() + return self.db.query(Submit).filter_by(member_id = member_id).count() ''' SELECT ''' def select_member_by_id(self, member_id): return self.db.query(Member).get(member_id) @@ -88,6 +88,8 @@ class ForumDBMixin(object): def count_reply_by_topic_id(self, topic_id): return self.db.query(Reply).filter_by(topic_id = topic_id).count() '''SELECT''' + def select_latest_node(self, count = 20): + return self.db.query(Node).order_by(desc(Node.id)).limit(count).all() def select_node_by_id(self, node_id): return self.db.query(Node).get(node_id) def select_node_by_link(self, link): @@ -162,7 +164,7 @@ def select_visible_problem_order_by_id(self, count = 10, start = 0): def select_latest_visible_problem_order_by_id(self, count = 10): return self.db.query(Problem).filter_by(invisible = 0).order_by(desc(Problem.id)).limit(count).all() def select_last_submit_by_problem_id_member_id(self, problem_id): - return self.db.query(Submit).filter_by(problem_id = problem_id).filter_by(member_id = self.current_user.id).order_by(desc(Submit.id)).all() + return self.db.query(Submit).filter_by(problem_id = problem_id).filter_by(member_id = self.current_user.id).order_by(desc(Submit.id)).limit(1).one() def select_submit_by_id(self, sid): return self.db.query(Submit).get(sid) def select_submit_order_by_id(self, count = 10, start = 0): diff --git a/less/style.less b/less/style.less index 5c3b7a3..4b0deda 100644 --- a/less/style.less +++ b/less/style.less @@ -173,8 +173,8 @@ a { .tag { .border-radius(4px); background-color: #EEE; - padding: 4px 4px 2px 10px; - float: left; + padding: 4px 10px; + display: inline; margin-right: 4px; margin-bottom: 5px; diff --git a/main.py b/main.py index 92743cd..a5ed1b2 100644 --- a/main.py +++ b/main.py @@ -2,7 +2,7 @@ # AUTHOR: Zeray Rice # FILE: main.py # CREATED: 01:37:19 08/03/2012 -# MODIFIED: 23:41:07 17/04/2012 +# MODIFIED: 22:08:52 18/04/2012 # DESCRIPTION: Main Server File, run as `python2 main.py [port_num]` import re @@ -51,7 +51,7 @@ def __init__(self): # self.db = tornado.database.Connection( # host=options.mysql_host, database=options.mysql_database, # user=options.mysql_user, password=options.mysql_password) - engine = create_engine(mysql_path, convert_unicode=True, echo=options.debug) + engine = create_engine(mysql_path, convert_unicode=True)#, echo=options.debug) models.init_db(engine) self.db = scoped_session(sessionmaker(bind=engine)) diff --git a/member.py b/member.py index bdcc44d..68d3509 100644 --- a/member.py +++ b/member.py @@ -2,12 +2,16 @@ # AUTHOR: Zeray Rice # FILE: member.py # CREATED: 02:18:23 09/03/2012 -# MODIFIED: 19:24:32 17/04/2012 +# MODIFIED: 20:29:11 18/04/2012 # DESCRIPTION: member handlers import re import copy +import uuid +import binascii import bcrypt +import datetime +from sqlalchemy.orm.exc import NoResultFound from tornado.web import HTTPError from tornado.web import authenticated @@ -32,8 +36,9 @@ def post(self): pwd = pwd.encode("utf-8") pwd = bcrypt.hashpw(pwd, self.settings['bcrypt_salt']) if not error: - member = self.select_member_by_usr_pwd(usr, pwd) - if not member: + try: + member = self.select_member_by_usr_pwd(usr, pwd) + except NoResultFound: error.append(self._("Wrong Username and password combination.")) if error: self.render("signin.html", locals()) @@ -42,7 +47,6 @@ def post(self): self.set_secure_cookie("auth", auth.secret) self.set_secure_cookie("uid", str(auth.member_id)) go_next = self.get_argument("next", default = None) - print go_next if go_next: self.redirect(go_next) return @@ -68,10 +72,12 @@ def post(self): member = Member() member.username = usr member.username_lower = usr.lower() - member.passowrd = bcrypt.hashpw(pwd, self.settings['bcrypt_salt']) + member.password = bcrypt.hashpw(pwd, self.settings['bcrypt_salt']) member.email = email member.gravatar_link = self.get_gravatar_url(email) - self.insert_member(member) + member.create = datetime.datetime.now() + self.db.add(member) + self.db.commit() auth = self.create_auth(member.id) self.set_secure_cookie('auth', auth.secret) self.set_secure_cookie('uid', str(auth.member_id)) @@ -198,7 +204,35 @@ def get(self): for member in members: member.accepted = self.count_accepted_by_member_id(member.id) member.submit = self.count_submit_by_member_id(member.id) - member.rating = member.accepted / float(member.submit) * 100 + member.rating = 0.0 + if member.submit: + member.rating = round(float(member.accepted) / member.submit * 100, 2) self.render("member_list.html", locals()) -__all__ = ["SigninHandler", "SignupHandler", "SignoutHandler", "SettingsHandler", "ChangePasswordHandler", "MemberHandler", "ListMemberHandler"] +class TestHandler(BaseHandler, MemberDBMixin): + def post(self): + usr = binascii.b2a_hex(uuid.uuid4().bytes)[3:10] + pwd = binascii.b2a_hex(uuid.uuid4().bytes)[3:10] + email = usr + "@gmail.com" + error = [] + error.extend(self.check_username(usr.lower(), queryDB = True)) + error.extend(self.check_password(pwd)) + error.extend(self.check_email(email, queryDB = True)) + if error: + self.render("signup.html", locals()) + return + member = Member() + member.username = usr + member.username_lower = usr.lower() + member.password = bcrypt.hashpw(pwd, self.settings['bcrypt_salt']) + member.email = email + member.gravatar_link = self.get_gravatar_url(email) + member.create = datetime.datetime.now() + self.db.add(member) + self.db.commit() + auth = self.create_auth(member.id) + self.set_secure_cookie('auth', auth.secret) + self.set_secure_cookie('uid', str(auth.member_id)) + self.redirect('/') + +__all__ = ["SigninHandler", "SignupHandler", "SignoutHandler", "SettingsHandler", "ChangePasswordHandler", "MemberHandler", "ListMemberHandler", "TestHandler"] diff --git a/problem.py b/problem.py index 4bd22e4..78700a4 100644 --- a/problem.py +++ b/problem.py @@ -2,10 +2,11 @@ # AUTHOR: Zeray Rice # FILE: problem.py # CREATED: 04:04:57 15/03/2012 -# MODIFIED: 02:22:02 18/04/2012 +# MODIFIED: 22:08:40 18/04/2012 import os import time +from sqlalchemy.orm.exc import NoResultFound from tornado.web import HTTPError from tornado.web import asynchronous @@ -128,7 +129,10 @@ def get(self): pages = self.get_page_count(count, 20) if self.current_user: for problem in problems: - problem.submit = self.select_last_submit_by_problem_id_member_id(problem.id) + try: + problem.submit = self.select_last_submit_by_problem_id_member_id(problem.id) + except NoResultFound: + problem.submit = None self.render("problem_list.html", locals()) class ViewTagHandler(BaseHandler, ProblemDBMixin): @@ -171,6 +175,7 @@ def get(self): submits = self.select_submit_order_by_id(10, start) pages = self.get_page_count(count) self.render("submit_list.html", locals()) +# self.db.close() class ViewSubmitHandler(BaseHandler, ProblemDBMixin): def get(self, sid): diff --git a/static/css/style.css b/static/css/style.css index 9f95f01..1ab0f15 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -3853,8 +3853,8 @@ a.nounderline:hover { -moz-border-radius: 4px; border-radius: 4px; background-color: #EEE; - padding: 4px 4px 2px 10px; - float: left; + padding: 4px 10px; + display: inline; margin-right: 4px; margin-bottom: 5px; } diff --git a/tpl/base/sidebar.html b/tpl/base/sidebar.html index 5fe898f..4ef58aa 100644 --- a/tpl/base/sidebar.html +++ b/tpl/base/sidebar.html @@ -52,13 +52,13 @@ {{ _('Submit') }} -