Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Alan Marchiori
labtool
Commits
49841f63
Commit
49841f63
authored
Dec 14, 2020
by
Alan Marchiori
Browse files
mongo code added
parent
fb990dcf
Changes
3
Hide whitespace changes
Inline
Side-by-side
commands/grade.py
View file @
49841f63
...
...
@@ -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
(
l
abpath
)
as
hist
:
with
History
(
l
ocation
=
labpath
,
dbpath
=
'{}/{}/{}'
.
format
(
coursename
,
student
,
labstr
)
)
as
hist
:
presults
=
[]
if
not
'check'
in
hist
:
hist
[
'check'
]
=
{}
...
...
config/__init__.py
View file @
49841f63
...
...
@@ -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"
utils/history.py
View file @
49841f63
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
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment