Skip to content
GitLab
Menu
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
f5aa9def
Commit
f5aa9def
authored
Jan 08, 2020
by
Alan Marchiori
Browse files
adding ta support
parent
1ebdc0f6
Changes
7
Hide whitespace changes
Inline
Side-by-side
Makefile
View file @
f5aa9def
CYTHON
=
cython
CPYFLAGS
=
-3
--embed
CC
=
gcc
#
CYTHON=cython
#
CPYFLAGS=-3 --embed
#
CC=gcc
#CFLAGS=`python3-config --cflags`
CFLAGS
=
-I
/nfs/software/anaconda-3.6/include/python3.6m
-I
/nfs/software/anaconda-3.6/include/python3.6m
-Wno-unused-result
-Wsign-compare
-march
=
nocona
-mtune
=
haswell
-ftree-vectorize
-fPIC
-fstack-protector-strong
-fno-lto
-fno-plt
-O3
-pipe
-fdebug-prefix-map
==
/usr/local/src/conda/-
-fdebug-prefix-map
==
/usr/local/src/conda-prefix
-fuse-linker-plugin
-DNDEBUG
-fwrapv
-O3
-Wall
#
CFLAGS=-I/nfs/software/anaconda-3.6/include/python3.6m -I/nfs/software/anaconda-3.6/include/python3.6m -Wno-unused-result -Wsign-compare -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-lto -fno-plt -O3 -pipe -fdebug-prefix-map==/usr/local/src/conda/- -fdebug-prefix-map==/usr/local/src/conda-prefix -fuse-linker-plugin -DNDEBUG -fwrapv -O3 -Wall
# -ffat-lto-objects -flto-partition=none -flto
LDFLAGS
=
`
python3-config
--ldflags
`
LIBS
=
all
:
lt
#LDFLAGS=`python3-config --ldflags`
#LIBS=
all
:
dist
.PHONY
:
dist clean deploy
#lt.c: lt.py
#$(CYTHON) $(CPYFLAGS) lt.py
l
t
:
dis
t
:
#
$(CC)
lt.c
-o
lt
-fno-lto
-fPIC
$(CFLAGS)
$(LDFLAGS)
$(LIBS)
rm
-rf
dist
./rev.py lt.py
chmod
go+rx lt.py
pyinstaller lt.py
chmod
-R
go+r dist
clean
:
rm
-f
lt.c deploy lt
deploy
:
lt
rm
-rf
~cs206/bin/lt
cp
-R
dist/lt ~cs206/bin
chmod
-R
go+r ~cs206/bin/lt
rm
-fr
lt.c deploy lt dist lt.spec
commands/check.py
View file @
f5aa9def
import
click
import
config
import
subprocess
from
config.echo
import
*
import
courses
from
config
import
UserConfig
...
...
@@ -33,40 +34,67 @@ class Checker:
else
:
# dicts can be used to specify tests to perform
for
cmd
,
check
in
test
.
items
():
if
'shell'
in
check
and
check
[
'shell'
]:
sh
=
True
else
:
sh
=
False
if
'stdin'
in
check
:
c
,
t
=
run
(
cmd
,
shell
=
sh
,
input
=
check
[
'stdin'
])
else
:
c
,
t
=
run
(
cmd
,
shell
=
sh
)
if
'message'
in
check
:
msg
=
check
[
'message'
]
else
:
msg
=
"$ {}"
.
format
(
cmd
)
sh
=
True
if
'shell'
in
check
and
check
[
'shell'
]
else
False
instr
=
check
[
'stdin'
]
if
'stdin'
in
check
else
None
to
=
check
[
'timeout'
]
if
'timeout'
in
check
else
2
# check for multiline inputs
if
instr
:
if
type
(
instr
)
==
list
:
instr
=
"
\n
"
.
join
(
instr
)
if
type
(
instr
)
!=
str
:
warn
(
"Rubric has non-string stdin ({})!"
.
format
(
type
(
instr
)))
instr
=
str
(
instr
)
if
to
>
2
:
warn
(
"Running {} with timeout {}s, please wait!"
.
format
(
cmd
,
to
))
try
:
c
,
t
=
run
(
cmd
,
shell
=
sh
,
input
=
instr
,
timeout
=
to
)
except
subprocess
.
TimeoutExpired
:
error
(
"{}: Command timeout!"
.
format
(
cmd
))
c
=
-
1
t
=
""
msg
=
check
[
'message'
]
if
'message'
in
check
else
"$ {}"
.
format
(
cmd
)
if
'returncode'
in
check
:
results
+=
[
c
==
check
[
'returncode'
]]
if
results
[
-
1
]:
success
(
"{}:
Reported
success."
.
format
(
msg
))
success
(
"{}: success."
.
format
(
msg
))
else
:
error
(
"{}:
Reported
fail
ur
e!"
.
format
(
msg
))
error
(
"{}: faile
d
!"
.
format
(
msg
))
error
(
t
)
# stop on first error
return
False
if
'stdout'
in
check
:
results
+=
[
t
==
check
[
'stdout'
]]
if
type
(
check
[
'stdout'
])
==
list
:
x
=
"
\n
"
.
join
(
check
[
'stdout'
])
elif
type
(
check
[
'stdout'
])
==
str
:
x
=
check
[
'stdout'
]
else
:
warn
(
"Rubric has non-string stdout!"
)
x
=
str
(
check
[
'stdout'
])
results
+=
[
t
==
x
]
if
results
[
-
1
]:
success
(
"{}: Output passed."
.
format
(
msg
))
else
:
error
(
"{}: Output not as expected (check formatting!)"
.
format
(
msg
))
for
line
in
difflib
.
context_diff
(
check
[
'stdout'
].
split
(
"
\n
"
),
t
.
split
(
"
\n
"
),
fromfile
=
'Expected output'
,
tofile
=
'Your output'
):
echo
(
line
.
strip
())
showdiff
=
True
if
'diff'
in
check
:
showdiff
=
check
[
'diff'
]
if
showdiff
:
error
(
"{}: Output not as expected (check formatting!)"
.
format
(
msg
))
for
line
in
difflib
.
context_diff
(
x
.
split
(
"
\n
"
),
t
.
split
(
"
\n
"
),
fromfile
=
'Expected output'
,
tofile
=
'Your output'
):
echo
(
line
.
strip
())
else
:
error
(
"{}: failed."
.
format
(
msg
))
return
False
return
all
(
results
)
...
...
@@ -75,7 +103,7 @@ class Checker:
dbg
(
'.exists({})'
.
format
(
args
))
for
fname
,
result
in
zip
(
args
,
map
(
os
.
path
.
exists
,
args
)):
if
not
result
:
error
(
"The file {} does not exist!"
.
format
(
fname
))
error
(
"The file
'
{}
'
does not exist!"
.
format
(
fname
))
return
False
return
True
...
...
@@ -189,8 +217,11 @@ def check(lab, part):
if
not
labname
:
error
(
"Could not detect LAB. Run this command from your lab folder or specify the LAB on the command line (--lab #)"
)
return
#courseobj = courses.all[coursename]
echo
(
"Checking {} of {}"
.
format
(
labname
,
coursename
))
if
part
:
echo
(
"Checking {} (part {}) of {}"
.
format
(
labname
,
part
,
coursename
))
else
:
echo
(
"Checking {} of {}"
.
format
(
labname
,
coursename
))
rubric
=
courses
.
load_rubric
(
coursename
,
labname
)
...
...
@@ -210,10 +241,10 @@ def check(lab, part):
os
.
path
.
join
(
coursepath
,
rubric
[
'path'
]))
newline
()
echo
(
"{}[{:25}({:3}) ]{}[{:3} points]{}"
.
format
(
"-"
*
10
,
info
[
'name'
][:
max
(
10
,
width
-
55
)].
ljust
(
width
-
55
),
xlen
=
47
# length of everything without name
echo
(
"Part {:3}: {}{}[{:3} points]{}"
.
format
(
info
[
'index'
],
info
[
'name'
][:
max
(
10
,
width
-
xlen
)].
ljust
(
width
-
xlen
),
"-"
*
10
,
info
[
'points'
],
"-"
*
10
))
...
...
@@ -230,6 +261,8 @@ def check(lab, part):
error
(
info
[
'on_error'
])
else
:
error
(
'This part failed!'
)
# stop checking on first part failure
break
# only check gitlab if all tests pass
if
all
(
presults
):
...
...
commands/init.py
View file @
f5aa9def
...
...
@@ -8,16 +8,40 @@ import shutil
from
config.echo
import
*
from
utils.gitlab
import
GitLab
from
utils.git
import
Git
from
utils.shell
import
run
import
courses
def
init_ta
(
coursename
,
localpath
):
"called when init sees the ta flag set."
localpath
+=
"-TA"
if
confirm
(
"Initialize {} into {} as a TA?"
.
format
(
coursename
,
localpath
)):
if
os
.
path
.
exists
(
localpath
):
# prompt to wipe it.
warn
(
"The path already exists!"
)
if
warn_confirm
(
"Would you like me to WIPE {} and re-create (this will DELETE ALL files)"
.
format
(
localpath
)):
shutil
.
rmtree
(
localpath
)
success
(
"Deleted {}"
.
format
(
localpath
))
if
os
.
path
.
exists
(
localpath
):
error
(
"ABORT: Cannot initialize since the path {} already exists!"
.
format
(
localpath
))
return
with
config
.
UserConfig
()
as
uc
:
uc
.
add_ta
(
name
=
coursename
,
path
=
localpath
)
@
click
.
command
(
short_help
=
'Initialize a course.'
)
@
click
.
argument
(
'course'
,
callback
=
validation
.
course
)
@
click
.
argument
(
'section'
,
callback
=
validation
.
section
)
@
click
.
argument
(
'semester'
,
callback
=
validation
.
semester
)
@
click
.
option
(
'--prefix'
,
default
=
None
,
@
click
.
option
(
'--prefix'
,
default
=
"~/"
,
help
=
"Override the default path prefix (~/)"
)
def
init
(
course
,
semester
,
section
,
prefix
):
@
click
.
option
(
"--ta"
,
default
=
False
,
help
=
"Set if you are a course TA or instructor."
,
is_flag
=
True
)
def
init
(
course
,
semester
,
section
,
prefix
,
ta
):
"""Initializes the lab tool structure on your local system
and on gitlab for a given COURSE, SECTION, and SEMESTER. Example: init CSCI206 S20 61.
"""
...
...
@@ -46,7 +70,9 @@ def init(course, semester, section, prefix):
course
=
course
,
semester
=
semester
,
section
=
section
)))
if
ta
:
init_ta
(
coursename
,
lp
)
return
if
confirm
(
"Initialize {} into {}?"
.
format
(
coursename
,
lp
)):
if
os
.
path
.
exists
(
lp
):
...
...
@@ -57,7 +83,7 @@ def init(course, semester, section, prefix):
success
(
"Deleted {}"
.
format
(
lp
))
if
os
.
path
.
exists
(
lp
):
error
(
"AB
R
OT: Cannot initalize since the path {} already exists!"
.
format
(
error
(
"ABO
R
T: Cannot init
i
alize since the path {} already exists!"
.
format
(
lp
))
return
...
...
@@ -154,7 +180,21 @@ def init(course, semester, section, prefix):
# finally clone the repo
git
=
Git
()
if
git
.
do_clone
(
repo
[
'ssh_url_to_repo'
],
lp
):
if
git
.
do_clone
(
repo
[
'ssh_url_to_repo'
],
localpath
=
lp
):
# copy cs206 gitignore and add to repo
igf
=
os
.
path
.
join
(
lp
,
'.gitignore'
)
src
=
"curl {} -o {}"
.
format
(
"http://eg.bucknell.edu/~cs206/.gitignore"
,
igf
)
c
,
t
=
run
(
src
)
if
c
==
0
:
success
(
src
)
git
.
do_push
(
addfiles
=
[
'.gitignore'
],
cwd
=
lp
,
message
=
'Added by labtool'
)
else
:
warn
(
"Failed to initialize gitignore file."
)
warn
(
src
)
warn
(
t
)
success
(
"Initialization complete!"
)
else
:
error
(
"Sorry, I was unable to clone the repo (did something go wrong earlier?)!"
)
config/user.py
View file @
f5aa9def
...
...
@@ -24,7 +24,11 @@ class UserConfig:
# self.cfg[x].append(val)
# else:
# self.cfg[x] = list(val)
def
add_ta
(
self
,
name
,
path
):
"add a course to the dict of ta courses: local_path"
if
not
'ta'
in
self
.
cfg
:
self
.
cfg
[
'ta'
]
=
{}
self
.
cfg
[
'ta'
][
name
]
=
path
def
add_course
(
self
,
name
,
path
):
"add a course to the dict of courses: local_path"
if
not
'courses'
in
self
.
cfg
:
...
...
lt.py
100755 → 100644
View file @
f5aa9def
...
...
@@ -20,8 +20,10 @@ import config
# CLI commands
import
commands
__version__
=
'1.0.0'
__version__
=
'1.0.1'
__date__
=
'2020-01-08T15:12:16.309992'
__user__
=
'cs206'
__host__
=
'linuxremote3.bucknell.edu'
@
click
.
group
()
def
main
():
"""Bucknell University Computer Science lab tool [lt].
...
...
@@ -36,7 +38,11 @@ def main():
@
main
.
command
()
def
version
():
"Display the version of labtool"
click
.
echo
(
"labtool version {}."
.
format
(
__version__
))
click
.
echo
(
"labtool version {} built on {} by {}@{}."
.
format
(
__version__
,
__date__
,
__user__
,
__host__
))
# attach all commands to the main cli entry group
for
cmd
in
commands
.
__all__
:
...
...
utils/git.py
View file @
f5aa9def
...
...
@@ -23,7 +23,7 @@ class Git:
def
status
(
self
,
cwd
):
"runs git status and returns the result"
return
shell
.
run
(
"git status"
,
cwd
=
cwd
)[
1
]
def
do_clone
(
self
,
giturl
,
localpath
=
None
,
cwd
=
'.'
,
branch
=
None
):
if
localpath
:
# localpath is where you want it like /home/amm042/CSCI206-S20-61
...
...
@@ -38,25 +38,29 @@ class Git:
echo
(
"Cloning {}... "
.
format
(
giturl
))
c
,
r
=
shell
.
run
(
cmd
,
cwd
=
cwd
)
if
c
!=
0
:
error
(
'[{}]$ {}'
.
format
(
cwd
,
cmd
))
error
(
r
)
else
:
success
(
'[{}]$ {}'
.
format
(
cwd
,
cmd
))
return
c
==
0
def
do_push
(
self
,
login
,
cwd
,
addfiles
=
[],
def
do_push
(
self
,
cwd
,
addfiles
=
[],
message
=
'A commit message'
,
branch
=
'master'
,
addall
=
False
):
#
# cmd = 'git branch {}'.format(branch)
# c,r = shell.run(cmd, cwd=cwd)
# if c != 0:
# error('[{}]$ {}'.format(cwd, cmd))
# error(r)
# else:
# success('[{}]$ {}'.format(cwd, cmd))
cmd
=
'git branch {}'
.
format
(
branch
)
c
,
r
=
shell
.
run
(
cmd
,
cwd
=
cwd
)
if
c
!=
0
:
error
(
r
)
else
:
success
(
'[{}]$ {}'
.
format
(
cwd
,
cmd
))
cmd
=
'git checkout {}'
.
format
(
branch
)
# -B creates the branch if missing
cmd
=
'git checkout -B {}'
.
format
(
branch
)
c
,
r
=
shell
.
run
(
cmd
,
cwd
=
cwd
)
if
c
!=
0
:
error
(
'[{}]$ {}'
.
format
(
cwd
,
cmd
))
error
(
r
)
else
:
success
(
'[{}]$ {}'
.
format
(
cwd
,
cmd
))
...
...
@@ -66,6 +70,7 @@ class Git:
echo
(
"Adding: "
,
cmd
)
c
,
r
=
shell
.
run
(
cmd
,
cwd
=
cwd
)
if
c
!=
0
:
error
(
'[{}]$ {}'
.
format
(
cwd
,
cmd
))
error
(
r
)
else
:
success
(
'[{}]$ {}'
.
format
(
cwd
,
cmd
))
...
...
@@ -82,6 +87,7 @@ class Git:
cmd
=
'git commit -m "{}"'
.
format
(
message
)
c
,
r
=
shell
.
run
(
cmd
,
cwd
=
cwd
)
if
c
!=
0
:
error
(
'[{}]$ {}'
.
format
(
cwd
,
cmd
))
error
(
r
)
else
:
success
(
'[{}]$ {}'
.
format
(
cwd
,
cmd
))
...
...
@@ -89,6 +95,7 @@ class Git:
cmd
=
'git push origin '
+
branch
c
,
r
=
shell
.
run
(
cmd
,
cwd
=
cwd
)
if
c
!=
0
:
error
(
'[{}]$ {}'
.
format
(
cwd
,
cmd
))
error
(
r
)
return
False
else
:
...
...
utils/shell.py
View file @
f5aa9def
...
...
@@ -2,7 +2,7 @@ import subprocess
import
os
import
shlex
def
run
(
cmd
,
cwd
=
None
,
input
=
None
,
shell
=
False
,
timeout
=
5
):
def
run
(
cmd
,
cwd
=
None
,
input
=
None
,
shell
=
False
,
timeout
=
3
):
result
=
subprocess
.
run
(
cmd
if
shell
else
shlex
.
split
(
cmd
),
executable
=
'/bin/bash'
if
shell
else
None
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a 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