Commit 49841f63 authored by Alan Marchiori's avatar Alan Marchiori
Browse files

mongo code added

parent fb990dcf
......@@ -52,10 +52,6 @@ def grade(lab, part, clone, dograde, regrade, user, skip, push):
coursename, coursepath))
error("You probably meant to run the check command, not grade.")
return
debug('COURSENAME: ', coursename)
debug('COURSEPATH: ', coursepath)
if not coursename:
error("The current directory is not an initialized course! You must first cd into an initialized course to check!")
return
......@@ -63,6 +59,9 @@ def grade(lab, part, clone, dograde, regrade, user, skip, push):
error("Could not detect LAB. Run this command from your lab folder or specify the LAB on the command line (--lab #)")
return
debug('COURSENAME: ', coursename)
debug('COURSEPATH: ', coursepath)
who = "{}@{}".format(os.environ['USER'], platform.node())
msg = "Grading {}".format(labname)
......@@ -135,8 +134,6 @@ def grade(lab, part, clone, dograde, regrade, user, skip, push):
else:
continue
if not os.path.isdir(labpath):
error(labpath+ " does not exist!")
if confirm("Do you want to create the student lab directory (this is required to grade)?", default=True):
......@@ -146,9 +143,10 @@ def grade(lab, part, clone, dograde, regrade, user, skip, push):
error("Path doesn't exist, cannot grade!")
continue
print('getting history for {} {} on lab {}.'.format(coursename, student, labstr))
# check for grade history
hfile = None
with History(labpath) as hist:
with History(location=labpath, dbpath='{}/{}/{}'.format(coursename, student, labstr)) as hist:
presults = []
if not 'check' in hist:
hist['check'] = {}
......
......@@ -29,3 +29,6 @@ gitlab_api_token_url = "https://gitlab.bucknell.edu/profile/personal_access_toke
# these fields are used to construct the gitlab server API endpoint
gitlab_url = "https://gitlab.bucknell.edu/"
gitlab_api = "api/v4/"
# mongodb collection name if using mongodb backend
labtool_mongodb_collection = "labtool"
import os
import os.path
import platform
import json
import sys
import config
from config.echo import debug, error
from pymongo import MongoClient
class HistoryConfigurationException(Exception):
pass
class History(dict):
"""A simple class to store grade history.
This is a dict class that is persisted as a json object.
It is meant to be used inside the with context manager.
eg:
rev2: now backend storage is configurable to a json file or mongodb.
'gradebackend' can be 'jsonfile' or 'mongodb'
if mongodb you must also set 'gradedb' to the mongodb connection string.
eg:
with History() as h:
h['...'] = ...
"""
backend_mongodb = 'mongodb'
backend_json = 'jsonfile'
dbclient = None
def exists(location=".", filename='.history.json'):
"class method to determine if a history file exists (w/o creation)"
return os.path.exists(os.path.join(location, filename))
def __init__(self, location=".",
def __init__(self, location=".", dbpath=None,
filename = '.history.json',
save = True,
*args, **kwargs):
"if save is false, never save the history file (read only copy)!"
dict.__init__(self, *args, **kwargs)
self.filename = filename
self.dbpath = dbpath
self.pathfile = os.path.join(location, filename)
self.rawjson = None
self.save = save
debug("using history file {}".format(
self.pathfile
))
self.who = "{}@{}".format(os.environ['USER'], platform.node())
# new feature, force userconfig backend config.
with config.UserConfig() as uc:
if 'gradebackend' not in uc.cfg:
raise HistoryConfigurationException("You must first configure the 'gradebackend' value in your userconfig.")
self.gradebackend = uc.cfg['gradebackend']
if 'gradedb' in uc.cfg:
self.gradedb = uc.cfg['gradedb']
else:
self.gradedb = None
if self.gradebackend == History.backend_mongodb:
# connect
if self.gradedb == None:
raise HistoryConfigurationException("You must first configure the 'gradedb' value in your userconfig.")
debug("using mongodb for history")
elif self.gradebackend == History.backend_json:
debug("using history file {}".format(self.pathfile))
else:
raise HistoryConfigurationException("Unsupported 'gradebackend' value in your userconfig.")
def __enter__(self):
"load history"
debug("HISTORY ENTER")
if os.path.exists(self.pathfile):
try:
with open(self.pathfile, 'r') as f:
self.rawjson = f.read()
try:
d = json.loads(self.rawjson)
except json.decoder.JSONDecodeError:
error("Grading history file at {} is corrupt. Manually remove or fix this file to continue running.".format(self.pathfile))
exit(212)
if self.gradebackend == History.backend_mongodb:
if History.dbclient == None:
# keep a global client to reuse
History.dbclient = MongoClient(self.gradedb)
self.mc = History.dbclient.get_default_database()[config.labtool_mongodb_collection]
d = self.mc.find_one({'path': self.dbpath})
if d and 'lock' in d:
warn ("The grade is currently locked by {}".format(d['lock']))
# prompt to take lock or abort
if d != None:
self.update(d)
except Exception as x:
print(x)
sys.exit()
# lock the document
if self.save:
self.mc.update_one(
{'_id': d['_id']},
{'$set': {'lock': self.who}})
else:
# insert empty document
if self.save:
r = self.mc.insert_one({
'path': self.dbpath,
'lock': self.who})
else:
r = self.mc.insert_one({'path': self.dbpath})
self['_id'] = r.inserted_id
else:
if os.path.exists(self.pathfile):
try:
with open(self.pathfile, 'r') as f:
self.rawjson = f.read()
try:
d = json.loads(self.rawjson)
except json.decoder.JSONDecodeError:
error("Grading history file at {} is corrupt. Manually remove or fix this file to continue running.".format(self.pathfile))
exit(212)
self.update(d)
except Exception as x:
print(x)
sys.exit()
return self
def __exit__(self, type, value, traceback):
"save history"
debug("HISTORY EXIT")
if not self.save:
return
# only save history if the target path exists
if os.path.exists(os.path.dirname(self.pathfile)):
s = json.dumps(
self,
indent=4,
sort_keys=True
)
# check if dirty.
if self.rawjson and self.rawjson == s:
debug("HISTORY is clean, no write.")
return
debug("HISTORY: write to {}".format(self.pathfile))
with open(self.pathfile, 'w') as f:
f.write(s)
if self.gradebackend == History.backend_mongodb:
# unlock so when saved, the document is not locked
if 'lock' in self:
del self['lock']
self.mc.replace_one(
{'_id': self['_id']},
self)
else:
# only save history if the target path exists
if os.path.exists(os.path.dirname(self.pathfile)):
s = json.dumps(
self,
indent=4,
sort_keys=True
)
# check if dirty.
if self.rawjson and self.rawjson == s:
debug("HISTORY is clean, no write.")
return
debug("HISTORY: write to {}".format(self.pathfile))
with open(self.pathfile, 'w') as f:
f.write(s)
if __name__=="__main__":
from pprint import pprint
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment