Skip to content

Commit

Permalink
Merge 3d38f46 into 6308752
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasyu888 committed Mar 6, 2021
2 parents 6308752 + 3d38f46 commit ca20297
Show file tree
Hide file tree
Showing 53 changed files with 3,799 additions and 2,775 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/sphinx-ghpages.yaml
@@ -1,5 +1,5 @@
name: "Pull Request Docs Check"
on:
on:
push:
branches:
- main
Expand Down
27 changes: 27 additions & 0 deletions .pre-commit-config.yaml
@@ -0,0 +1,27 @@
repos:

- repo: https://github.com/ambv/black
rev: 20.8b1
hooks:
- id: black
language_version: python3
- repo: https://github.com/pycqa/isort
rev: 5.7.0
hooks:
- id: isort
args: ["--profile", "black", "--filter-files"]
- repo: https://github.com/asottile/pyupgrade
rev: v2.10.0
hooks:
- id: pyupgrade
args: [--py36-plus]
# - repo: https://github.com/asottile/blacken-docs
# rev: v1.8.0
# hooks:
# - id: blacken-docs
# additional_dependencies: [black==20.8b1]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: trailing-whitespace
- id: flake8
51 changes: 41 additions & 10 deletions bin/run_writeup_archiver.py
@@ -1,31 +1,62 @@
import signal
import time
import os
import signal
import subprocess
import time


class GracefulKiller:
kill_now = False

def __init__(self):
signal.signal(signal.SIGINT, self.exit_gracefully)
signal.signal(signal.SIGTERM, self.exit_gracefully)

def exit_gracefully(self,signum, frame):
def exit_gracefully(self, signum, frame):
self.kill_now = True

if __name__ == '__main__':

if __name__ == "__main__":
killer = GracefulKiller()
while True:
synUser = os.environ['SYNAPSE_USERNAME']
synPass = os.environ['SYNAPSE_PASSWORD']
chalName = os.environ['CHALLENGE_NAME']
synUser = os.environ["SYNAPSE_USERNAME"]
synPass = os.environ["SYNAPSE_PASSWORD"]
chalName = os.environ["CHALLENGE_NAME"]

validateSub = ['python','challenge.py','--challengeName',chalName,'-u',synUser,'-p',synPass,'--send-messages','--notifications','--acknowledge-receipt','validate','9603284','--admin','3336298']
archiveSub = ['python','challenge.py','--challengeName',chalName,'-u',synUser,'-p',synPass,'--notifications','archive','9603284']
validateSub = [
"python",
"challenge.py",
"--challengeName",
chalName,
"-u",
synUser,
"-p",
synPass,
"--send-messages",
"--notifications",
"--acknowledge-receipt",
"validate",
"9603284",
"--admin",
"3336298",
]
archiveSub = [
"python",
"challenge.py",
"--challengeName",
chalName,
"-u",
synUser,
"-p",
synPass,
"--notifications",
"archive",
"9603284",
]

subprocess.call(validateSub, stderr=subprocess.STDOUT)
subprocess.call(archiveSub, stderr=subprocess.STDOUT)

time.sleep(43200)
if killer.kill_now:
break
print("End of the program. I was killed gracefully :)")
print("End of the program. I was killed gracefully :)")
196 changes: 119 additions & 77 deletions bin/runqueue.py
Expand Up @@ -6,26 +6,28 @@
from datetime import timedelta

import synapseclient
from synapseclient.exceptions import SynapseAuthenticationError
from synapseclient.exceptions import SynapseNoCredentialsError
from synapseclient.exceptions import (
SynapseAuthenticationError,
SynapseNoCredentialsError,
)

from scoring_harness import lock

logging.basicConfig(format='%(asctime)s %(message)s')
logging.basicConfig(format="%(asctime)s %(message)s")
LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.INFO)


def import_config_py(config_path):
'''
"""
Uses importlib to import users configuration
Args:
config_path: Path to configuration python script
Returns:
module
'''
"""
spec = importlib.util.spec_from_file_location("config", config_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
Expand All @@ -35,18 +37,28 @@ def import_config_py(config_path):
# ==================================================
# Handlers for command
# ==================================================
def command(syn, evaluation_queue_maps, admin_user_ids=None, dry_run=False,
remove_cache=False, send_messages=False, notifications=True):
def command(
syn,
evaluation_queue_maps,
admin_user_ids=None,
dry_run=False,
remove_cache=False,
send_messages=False,
notifications=True,
):
for queueid in evaluation_queue_maps:
for config in evaluation_queue_maps[queueid]:
invoke_func = config['func']
invoke = invoke_func(syn, queueid,
admin_user_ids=admin_user_ids,
dry_run=dry_run,
remove_cache=remove_cache,
send_messages=send_messages,
notifications=notifications,
**config['kwargs'])
invoke_func = config["func"]
invoke = invoke_func(
syn,
queueid,
admin_user_ids=admin_user_ids,
dry_run=dry_run,
remove_cache=remove_cache,
send_messages=send_messages,
notifications=notifications,
**config["kwargs"],
)
invoke()


Expand All @@ -55,63 +67,79 @@ def main(args):
# Synapse login
try:
if args.synapse_config is not None:
syn = synapseclient.Synapse(debug=args.debug,
configPath=args.synapse_config)
syn = synapseclient.Synapse(
debug=args.debug, configPath=args.synapse_config
)
else:
syn = synapseclient.Synapse(debug=args.debug)
syn.login(silent=True)
except (SynapseAuthenticationError, SynapseNoCredentialsError):
raise ValueError("Must provide Synapse credentials as parameters or "
"through a Synapse config file.")
raise ValueError(
"Must provide Synapse credentials as parameters or "
"through a Synapse config file."
)

# TODO: Check challenge admin ids
if args.admin_user_ids is None:
args.admin_user_ids = [syn.getUserProfile()['ownerId']]
args.admin_user_ids = [syn.getUserProfile()["ownerId"]]

try:
module = import_config_py(args.config_path)
except Exception:
raise ValueError("Error importing your python config script")

check_keys = set(["id", "func", 'kwargs'])
check_keys = {"id", "func", "kwargs"}
evaluation_queue_maps = {}
for queue in module.EVALUATION_QUEUES_CONFIG:
if not check_keys.issubset(queue.keys()):
raise KeyError("You must specify 'id', 'func', 'kwargs'"
"for each of your evaluation queues"
"in your EVALUATION_QUEUES_CONFIG")
raise KeyError(
"You must specify 'id', 'func', 'kwargs'"
"for each of your evaluation queues"
"in your EVALUATION_QUEUES_CONFIG"
)
# evaluation_queue_maps[queue['id']] = queue
if evaluation_queue_maps.get(queue['id']):
evaluation_queue_maps[queue['id']].append(queue)
if evaluation_queue_maps.get(queue["id"]):
evaluation_queue_maps[queue["id"]].append(queue)
else:
evaluation_queue_maps[queue['id']] = [queue]
evaluation_queue_maps[queue["id"]] = [queue]

if args.evaluation:
try:
eval_queues = {evalid: evaluation_queue_maps[evalid]
for evalid in args.evaluation}
eval_queues = {
evalid: evaluation_queue_maps[evalid]
for evalid in args.evaluation
}
except KeyError:
raise ValueError("If evaluation is specified, must match an 'id' "
"in EVALUATION_QUEUES_CONFIG")
raise ValueError(
"If evaluation is specified, must match an 'id' "
"in EVALUATION_QUEUES_CONFIG"
)
else:
eval_queues = evaluation_queue_maps

# Acquire lock, don't run two scoring scripts at once
try:
update_lock = lock.acquire_lock_or_fail('challenge',
max_age=timedelta(hours=4))
update_lock = lock.acquire_lock_or_fail(
"challenge", max_age=timedelta(hours=4)
)
except lock.LockedException:
LOGGER.error("Is the scoring script already running? "
"Can't acquire lock.")
LOGGER.error(
"Is the scoring script already running? " "Can't acquire lock."
)
# can't acquire lock, so return error code 75 which is a
# temporary error according to /usr/include/sysexits.h
return 75

try:
command(syn, eval_queues, admin_user_ids=args.admin_user_ids,
dry_run=args.dry_run, remove_cache=args.remove_cache,
send_messages=args.send_messages,
notifications=args.notifications)
command(
syn,
eval_queues,
admin_user_ids=args.admin_user_ids,
dry_run=args.dry_run,
remove_cache=args.remove_cache,
send_messages=args.send_messages,
notifications=args.notifications,
)
except Exception as e:
LOGGER.error(e)

Expand All @@ -120,48 +148,62 @@ def main(args):
return 0


if __name__ == '__main__':
if __name__ == "__main__":
parser = argparse.ArgumentParser()

parser.add_argument("config_path",
help="path to config.py")

parser.add_argument("-c", "--synapse_config",
help="Path to Synapse Config File")

parser.add_argument("--notifications",
help="Send error notifications to challenge admins",
action="store_true")

parser.add_argument("--send-messages",
help="Send validation and scoring messages to participants",
action="store_true")

parser.add_argument("--dry-run",
help="Perform the requested command without updating anything in Synapse",
action="store_true")

parser.add_argument("--remove-cache",
help="If 'validate' step, removes invalid submissions from cache. "
"If 'score' step, removes scored submissions from cache.",
action="store_true")

parser.add_argument("--debug",
help="Show verbose error output from Synapse API calls",
action="store_true")
parser.add_argument("config_path", help="path to config.py")

parser.add_argument(
"-c", "--synapse_config", help="Path to Synapse Config File"
)

parser.add_argument(
"--notifications",
help="Send error notifications to challenge admins",
action="store_true",
)

parser.add_argument(
"--send-messages",
help="Send validation and scoring messages to participants",
action="store_true",
)

parser.add_argument(
"--dry-run",
help="Perform the requested command without updating anything in Synapse",
action="store_true",
)

parser.add_argument(
"--remove-cache",
help="If 'validate' step, removes invalid submissions from cache. "
"If 'score' step, removes scored submissions from cache.",
action="store_true",
)

parser.add_argument(
"--debug",
help="Show verbose error output from Synapse API calls",
action="store_true",
)

# Add these subparsers after because it takes multiple arguments
parser.add_argument('-a',
"--admin-user-ids",
help="Synapse user ids. Defaults to the user running the script",
nargs='+',
default=None)

parser.add_argument("--evaluation",
help="Evaluation id(s) to validate/score. If not specified, script "
"will validate/score all evaluations set in EVALUATION_QUEUES_CONFIG",
nargs='+',
default=None)
parser.add_argument(
"-a",
"--admin-user-ids",
help="Synapse user ids. Defaults to the user running the script",
nargs="+",
default=None,
)

parser.add_argument(
"--evaluation",
help="Evaluation id(s) to validate/score. If not specified, script "
"will validate/score all evaluations set in EVALUATION_QUEUES_CONFIG",
nargs="+",
default=None,
)

args = parser.parse_args()
LOGGER.info("=" * 30)
Expand Down
5 changes: 2 additions & 3 deletions challengeutils/__init__.py
@@ -1,3 +1,2 @@
from . import discussion
from . import permissions
from .__version__ import __version__
from . import discussion, permissions
from .__version__ import __version__

0 comments on commit ca20297

Please sign in to comment.