Skip to content

Commit e37fafd

Browse files
committed
Merge 'rebased'
1 parent 9ee65b7 commit e37fafd

File tree

116 files changed

+5417
-1130
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+5417
-1130
lines changed

AUTHORS.txt

+5-1
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,20 @@ Vytis Banaitis <[email protected]>
1515
Giovanni Campagna (aka gcampax) <[email protected]>
1616
Cheng, Ting-Yuan (aka magrady24) <[email protected]>
1717
William Di Luigi (aka wil93) <[email protected]>
18+
Johannes Kapfhammer (aka kapf) <[email protected]>
1819
Vittorio Gambaletta (aka VittGam) <[email protected]>
1920
David Greenaway <[email protected]>
2021
Fabian Gundlach (aka fagu) <[email protected]>
2122
Masaki Hara (aka qnighy) <[email protected]>
22-
Artem Iglikov (aka arti) <[email protected]>
23+
Artem Iglikov (aka artikz) <[email protected]>
2324
Damien Leroy <[email protected]>
25+
Tubérculo Martínez <[email protected]>
2426
Evgeny Martynov <[email protected]>
2527
Kento Nikaido (aka snukent) <[email protected]>
2628
William Pettersson <[email protected]>
29+
Ludwig Schmidt <[email protected]>
2730
Federico Scrinzi (aka volpino) <[email protected]>
31+
Konstantin Tretyakov <[email protected]>
2832
Luca Versari <[email protected]>
2933
Hyungsuk Yoon <[email protected]>
3034
Kenneth Wong <[email protected]>

REQUIREMENTS.txt

+1
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ gevent>=1.0
1717
werkzeug>=0.8
1818
pycups>=1.9
1919
PyPDF2>=1.19
20+
patool>=1.7

cms/__init__.py

+30-1
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@
3636
__all__ = [
3737
"LANG_C", "LANG_CPP", "LANG_PASCAL", "LANG_PYTHON", "LANG_PHP",
3838
"LANGUAGE_NAMES", "LANGUAGES", "DEFAULT_LANGUAGES",
39-
"SOURCE_EXT_TO_LANGUAGE_MAP",
39+
"SOURCE_EXT_TO_LANGUAGE_MAP", "filename_to_language",
4040
"LANGUAGE_TO_SOURCE_EXT_MAP", "LANGUAGE_TO_HEADER_EXT_MAP",
41+
"LANGUAGE_TO_OBJ_EXT_MAP",
42+
"SCORE_MODE_MAX", "SCORE_MODE_MAX_TOKENED_LAST",
4143
# log
4244
# Nothing intended for external use, no need to advertise anything.
4345
# util
@@ -102,7 +104,34 @@
102104
LANG_CPP: ".h",
103105
LANG_PASCAL: "lib.pas",
104106
}
107+
LANGUAGE_TO_OBJ_EXT_MAP = {
108+
LANG_C: ".o",
109+
LANG_CPP: ".o",
110+
LANG_PASCAL: ".o",
111+
}
112+
113+
114+
def filename_to_language(filename):
115+
"""Determine the programming language of filename from its extension.
116+
117+
filename (string): the file to test.
118+
119+
return (string|None): the extension of filename, or None if it is
120+
not a recognized language.
121+
122+
"""
123+
for source_ext, language in SOURCE_EXT_TO_LANGUAGE_MAP.iteritems():
124+
if filename.endswith(source_ext):
125+
return language
126+
return None
127+
128+
129+
# Task score modes.
105130

131+
# Maximum score amongst all submissions.
132+
SCORE_MODE_MAX = "max"
133+
# Maximum score among all tokened submissions and the last submission.
134+
SCORE_MODE_MAX_TOKENED_LAST = "max_tokened_last"
106135

107136
from .util import ConfigError, mkdir, utf8_decoder, Address, ServiceCoord, \
108137
get_safe_shard, get_service_address, get_service_shards, \

cms/conf.py

+10-6
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
# Contest Management System - http://cms-dev.github.io/
55
# Copyright © 2010-2014 Giovanni Mascellani <[email protected]>
6-
# Copyright © 2010-2012 Stefano Maggiolo <[email protected]>
6+
# Copyright © 2010-2015 Stefano Maggiolo <[email protected]>
77
# Copyright © 2010-2012 Matteo Boscariol <[email protected]>
88
# Copyright © 2013 Luca Wehrstedt <[email protected]>
99
# Copyright © 2014 Fabian Gundlach <[email protected]>
@@ -41,8 +41,8 @@
4141
class Config(object):
4242
"""This class will contain the configuration for CMS. This needs
4343
to be populated at the initilization stage. This is loaded by
44-
default with some sane data. See cms.conf.sample in the examples
45-
for information on the meaning of the fields.
44+
default with some sane data. See cms.conf.sample in the config
45+
directory for information on the meaning of the fields.
4646
4747
"""
4848
def __init__(self):
@@ -68,8 +68,12 @@ def __init__(self):
6868
self.use_cgroups = True
6969
self.sandbox_implementation = 'isolate'
7070

71+
# Sandbox.
72+
self.max_file_size = 1048576
73+
7174
# WebServers.
72-
self.secret_key = "8e045a51e4b102ea803c06f92841a1fb"
75+
self.secret_key_default = "8e045a51e4b102ea803c06f92841a1fb"
76+
self.secret_key = self.secret_key_default
7377
self.tornado_debug = False
7478

7579
# ContestWebServer.
@@ -134,11 +138,11 @@ def __init__(self):
134138
self.cache_dir = "cache"
135139
self.data_dir = "lib"
136140
self.run_dir = "run"
137-
paths = [os.path.join(".", "examples", "cms.conf")]
141+
paths = [os.path.join(".", "config", "cms.conf")]
138142
if '__file__' in globals():
139143
paths += [os.path.abspath(os.path.join(
140144
os.path.dirname(__file__),
141-
'..', 'examples', 'cms.conf'))]
145+
'..', 'config', 'cms.conf'))]
142146
paths += [os.path.join("/", "usr", "local", "etc", "cms.conf"),
143147
os.path.join("/", "etc", "cms.conf")]
144148

cms/db/__init__.py

+36-8
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
# Contest Management System - http://cms-dev.github.io/
55
# Copyright © 2010-2012 Giovanni Mascellani <[email protected]>
6-
# Copyright © 2010-2012 Stefano Maggiolo <[email protected]>
6+
# Copyright © 2010-2015 Stefano Maggiolo <[email protected]>
77
# Copyright © 2010-2012 Matteo Boscariol <[email protected]>
88
# Copyright © 2013 Bernard Blackham <[email protected]>
99
# Copyright © 2013 Luca Wehrstedt <[email protected]>
@@ -32,7 +32,7 @@
3232
import logging
3333

3434
from sqlalchemy import create_engine
35-
from sqlalchemy.orm import joinedload, configure_mappers
35+
from sqlalchemy.orm import configure_mappers, joinedload, subqueryload
3636

3737
from cms import config
3838

@@ -85,11 +85,11 @@
8585

8686
# Instantiate or import these objects.
8787

88-
version = 13
88+
version = 14
8989

9090

9191
engine = create_engine(config.database, echo=config.database_debug,
92-
pool_size=20, pool_recycle=120)
92+
pool_size=20, max_overflow=20, pool_recycle=120)
9393

9494

9595
from .session import Session, ScopedSession, SessionGen, \
@@ -125,7 +125,7 @@
125125
# file because of circular dependencies.
126126

127127
def get_submissions(self):
128-
"""Returns a list of submissions (with the information about the
128+
"""Return a list of submissions (with the information about the
129129
corresponding task) referring to the contest.
130130
131131
returns (list): list of submissions.
@@ -138,11 +138,11 @@ def get_submissions(self):
138138

139139

140140
def get_submission_results(self):
141-
"""Returns a list of submission results for all submissions in
141+
"""Return a list of submission results for all submissions in
142142
the current contest, as evaluated against the active dataset
143143
for each task.
144144
145-
returns (list): list of submission results.
145+
returns ([SubmissionResult]): list of submission results.
146146
147147
"""
148148
return self.sa_session.query(SubmissionResult)\
@@ -152,7 +152,7 @@ def get_submission_results(self):
152152

153153

154154
def get_user_tests(self):
155-
"""Returns a list of user tests (with the information about the
155+
"""Return a list of user tests (with the information about the
156156
corresponding user) referring to the contest.
157157
158158
return (list): list of user tests.
@@ -182,6 +182,34 @@ def get_user_test_results(self):
182182
Contest.get_user_test_results = get_user_test_results
183183

184184

185+
# The following is a method of Dataset that cannot be put in the right
186+
# file because of circular dependencies.
187+
188+
def get_submission_results_for_dataset(self, dataset):
189+
"""Return a list of all submission results against the specified
190+
dataset.
191+
192+
Also preloads the executable and evaluation objects relative to
193+
the submission results.
194+
195+
returns ([SubmissionResult]): list of submission results.
196+
197+
"""
198+
# We issue this query manually to optimize it: we load all
199+
# executables and evaluations at once instead of having SA
200+
# lazy-load them when we access them for each SubmissionResult,
201+
# one at a time.
202+
return self.sa_session\
203+
.query(SubmissionResult)\
204+
.filter(SubmissionResult.dataset == dataset)\
205+
.options(joinedload(SubmissionResult.submission))\
206+
.options(subqueryload(SubmissionResult.executables))\
207+
.options(subqueryload(SubmissionResult.evaluations))\
208+
.all()
209+
210+
Dataset.get_submission_results = get_submission_results_for_dataset
211+
212+
185213
# The following is a method of User that cannot be put in the right
186214
# file because of circular dependencies.
187215

cms/db/filecacher.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,7 @@ def check_backend_integrity(self, delete=False):
780780
781781
"""
782782
clean = True
783-
for digest, description in self.list():
783+
for digest, _ in self.list():
784784
fobj = self.backend.get_file(digest)
785785
hasher = hashlib.sha1()
786786
try:

cms/db/submission.py

+47-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
# Contest Management System - http://cms-dev.github.io/
55
# Copyright © 2010-2012 Giovanni Mascellani <[email protected]>
6-
# Copyright © 2010-2012 Stefano Maggiolo <[email protected]>
6+
# Copyright © 2010-2014 Stefano Maggiolo <[email protected]>
77
# Copyright © 2010-2012 Matteo Boscariol <[email protected]>
88
# Copyright © 2012-2013 Luca Wehrstedt <[email protected]>
99
# Copyright © 2013 Bernard Blackham <[email protected]>
@@ -362,10 +362,11 @@ def get_evaluation(self, testcase):
362362
"""Return the Evaluation of this SR on the given Testcase, if any
363363
364364
testcase (Testcase): the testcase the returned evaluation will
365-
belong to
366-
return (Evaluation): the (only!) evaluation of this submission
367-
result on the given testcase, or None if
368-
there isn't any.
365+
belong to.
366+
367+
return (Evaluation|None): the (only!) evaluation of this
368+
submission result on the given testcase, or None if there
369+
isn't any.
369370
370371
"""
371372
# Use IDs to avoid triggering a lazy-load query.
@@ -388,6 +389,13 @@ def compiled(self):
388389
"""
389390
return self.compilation_outcome is not None
390391

392+
@staticmethod
393+
def filter_compiled():
394+
"""Return a filtering expression for compiled submission results.
395+
396+
"""
397+
return SubmissionResult.compilation_outcome != None # noqa
398+
391399
def compilation_failed(self):
392400
"""Return whether the submission result did not compile.
393401
@@ -398,6 +406,14 @@ def compilation_failed(self):
398406
"""
399407
return self.compilation_outcome == "fail"
400408

409+
@staticmethod
410+
def filter_compilation_failed():
411+
"""Return a filtering expression for submission results failing
412+
compilation.
413+
414+
"""
415+
return SubmissionResult.compilation_outcome == "fail"
416+
401417
def compilation_succeeded(self):
402418
"""Return whether the submission compiled.
403419
@@ -408,6 +424,14 @@ def compilation_succeeded(self):
408424
"""
409425
return self.compilation_outcome == "ok"
410426

427+
@staticmethod
428+
def filter_compilation_succeeded():
429+
"""Return a filtering expression for submission results passing
430+
compilation.
431+
432+
"""
433+
return SubmissionResult.compilation_outcome == "ok"
434+
411435
def evaluated(self):
412436
"""Return whether the submission result has been evaluated.
413437
@@ -416,6 +440,13 @@ def evaluated(self):
416440
"""
417441
return self.evaluation_outcome is not None
418442

443+
@staticmethod
444+
def filter_evaluated():
445+
"""Return a filtering lambda for evaluated submission results.
446+
447+
"""
448+
return SubmissionResult.evaluation_outcome != None # noqa
449+
419450
def needs_scoring(self):
420451
"""Return whether the submission result needs to be scored.
421452
@@ -436,6 +467,17 @@ def scored(self):
436467
"public_score", "public_score_details",
437468
"ranking_score_details"])
438469

470+
@staticmethod
471+
def filter_scored():
472+
"""Return a filtering lambda for scored submission results.
473+
474+
"""
475+
return ((SubmissionResult.score != None)
476+
& (SubmissionResult.score_details != None)
477+
& (SubmissionResult.public_score != None)
478+
& (SubmissionResult.public_score_details != None)
479+
& (SubmissionResult.ranking_score_details != None)) # noqa
480+
439481
def invalidate_compilation(self):
440482
"""Blank all compilation and evaluation outcomes, and the score.
441483

0 commit comments

Comments
 (0)