check.py 5.78 KB
Newer Older
Alan Marchiori's avatar
initial  
Alan Marchiori committed
1
2
import click
import config
Alan Marchiori's avatar
Alan Marchiori committed
3

Alan Marchiori's avatar
Alan Marchiori committed
4
import subprocess
Alan Marchiori's avatar
Alan Marchiori committed
5
6
7
from config.echo import *
import courses
from config import UserConfig
Alan Marchiori's avatar
Alan Marchiori committed
8
from utils.shell import run
Alan Marchiori's avatar
Alan Marchiori committed
9
10
from utils.git import Git

Alan Marchiori's avatar
Alan Marchiori committed
11
from pprint import pprint
Alan Marchiori's avatar
Alan Marchiori committed
12
import os
Alan Marchiori's avatar
Alan Marchiori committed
13
from pathlib import Path
14
import shutil
Alan Marchiori's avatar
Alan Marchiori committed
15
import difflib
Alan Marchiori's avatar
Alan Marchiori committed
16

Alan Marchiori's avatar
Alan Marchiori committed
17
from commands.checker import Checker
Alan Marchiori's avatar
Alan Marchiori committed
18
from utils.history import History
Alan Marchiori's avatar
Alan Marchiori committed
19

Alan Marchiori's avatar
Alan Marchiori committed
20
21
22
def dbg(x):
    debug(__name__ + x)

Alan Marchiori's avatar
Alan Marchiori committed
23
24
def show_report(hist, partstr, info):
    "show a nicely formatted grade report."
Alan Marchiori's avatar
Alan Marchiori committed
25
26

    width = min(120, shutil.get_terminal_size().columns)
Alan Marchiori's avatar
Alan Marchiori committed
27

Alan Marchiori's avatar
Alan Marchiori committed
28
    if partstr == 'TOTAL':
Alan Marchiori's avatar
Alan Marchiori committed
29
30
31
32
33
34
35
36
37
38
        newline()
        echo("-"*width)
        newline()
        echo("Total: {} of {}".format(
            hist['grade']['TOTAL']['grade'],
            hist['grade']['TOTAL']['total']
        ))
        echo("Graded by {}".format(
            hist['grade']['TOTAL']['who']
        ))
Alan Marchiori's avatar
Alan Marchiori committed
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
    else:
        newline()
        xlen = 47 # length of everything without name
        echo("Part {:3}: {}".format(
            info['index'],
            info['name'][:max(10,width-xlen)].ljust(width-xlen)
            ))
        echo(info['prompt'])

        if partstr in hist['grade']:
            echo('\tGrade: {} of {}'.format(
                hist['grade'][partstr]['grade'],
                hist['grade'][partstr]['total']))

            if hist['grade'][partstr]['comment'] != '':
                echo('\tComment: {}'.format(
                    hist['grade'][partstr]['comment']))
        else:
            warn("Part {:3} is ungraded ({})!".format(
                info['index'], partstr
                ))
    #
    # if 'TOTAL' in hist['grade']:
    #     newline()
    #     echo("-"*width)
    #     newline()
    #     echo("Total: {} of {}".format(
    #         hist['grade']['TOTAL']['grade'],
    #         hist['grade']['TOTAL']['total']
    #     ))
    #     echo("Graded by {}".format(
    #         hist['grade']['TOTAL']['who']
    #     ))
Alan Marchiori's avatar
Alan Marchiori committed
72

Alan Marchiori's avatar
Alan Marchiori committed
73
74
75
76
77
78
79
@click.command(short_help="Check LAB")
@click.option('--lab', type=int, default=None)
@click.option('--part', type=int, default=None)
def check(lab, part):
    """check LAB and PART without submitting. If LAB is
    omitted, we will attempt to auto detect from the working directory. If PART
    is omitted, ALL parts are checked.
Alan Marchiori's avatar
initial  
Alan Marchiori committed
80
    """
Alan Marchiori's avatar
Alan Marchiori committed
81

Alan Marchiori's avatar
Alan Marchiori committed
82
83
84
85
86
    # convert lab number to filename magic.
    if lab:
        labstr = "lab{:02}".format(lab)
    else:
        labstr = None
Alan Marchiori's avatar
Alan Marchiori committed
87
    coursename, coursepath, labname, ista = courses.detect_course(lab=labstr)
Alan Marchiori's avatar
Alan Marchiori committed
88

Alan Marchiori's avatar
Alan Marchiori committed
89
90
91
    if not coursename:
        error("The current directory is not an initialized course! You must first cd into an initialized course to check!")
        return
Alan Marchiori's avatar
Alan Marchiori committed
92
93
94
    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
Alan Marchiori's avatar
Alan Marchiori committed
95
96
97
98
99

    if part:
        echo("Checking {} (part {}) of {}".format(labname, part, coursename))
    else:
        echo("Checking {} of {}".format(labname, coursename))
Alan Marchiori's avatar
Alan Marchiori committed
100

Alan Marchiori's avatar
Alan Marchiori committed
101
    rubric = courses.load_rubric(coursename, labname)
Alan Marchiori's avatar
Alan Marchiori committed
102
103

    if not rubric:
Alan Marchiori's avatar
Alan Marchiori committed
104
        error("{} is not defined for the course {}.".format(
Alan Marchiori's avatar
Alan Marchiori committed
105
            labname, coursename
Alan Marchiori's avatar
Alan Marchiori committed
106
107
        ))
        return
108
    width = min(120, shutil.get_terminal_size().columns)
Alan Marchiori's avatar
Alan Marchiori committed
109

Alan Marchiori's avatar
Alan Marchiori committed
110
111
112
113
114
115
116
117
118
119
120
121
    if ista:
        error("Check only works in the student context, you are in a TA course path!")
        error("{} is a TA path for {}!".format(
            coursepath, coursename
        ))
        error("You probably want to use the grade command (maybe with --no-dograde)")
        return

    else:
        labpath = os.path.join(coursepath, rubric['path'])

    # check for a history file to see if the lab has been graded
Alan Marchiori's avatar
Alan Marchiori committed
122
123
124
    # if History.exists(location=labpath):
    #     return show_report(rubric, labpath)
    #     return
Alan Marchiori's avatar
Alan Marchiori committed
125

Alan Marchiori's avatar
Alan Marchiori committed
126
127
128
129
    with History(location=labpath, save=False) as hist:
        presults = []
        for partstr, info in rubric['parts'].items():
            if isinstance(part, int) and part != info['index']:
Alan Marchiori's avatar
Alan Marchiori committed
130
                continue
Alan Marchiori's avatar
Alan Marchiori committed
131
132
133
134
135
136
137
138

            if 'grade' in hist and partstr in hist['grade']:
                show_report(hist, partstr, info)
                continue

            if 'check' in info:
                if 'check' in hist and partstr in hist['check']:
                    presults += hist['check'][partstr]['result']
Alan Marchiori's avatar
Alan Marchiori committed
139
                else:
Alan Marchiori's avatar
Alan Marchiori committed
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
                    c = Checker(info, labpath)

                    newline()
                    xlen = 47 # length of everything without name
                    echo("Part {:3}: {}".format(
                        info['index'],
                        info['name'][:max(10,width-xlen)].ljust(width-xlen)
                        ))
                    echo(info['prompt'])
                    if c.do_check():
                        presults += [True]
                        if 'on_pass' in info:
                            success(info['on_pass'])
                        else:
                            success('This part passed!')
                    else:
                        presults += [False]
                        if 'on_error' in info:
                            error(info['on_error'])
                        else:
                            error('This part failed!')
                        # stop checking on first part failure
                        break
163

Alan Marchiori's avatar
Alan Marchiori committed
164
165
166
167
        # show total grade at the end, if it's graded.
        if 'grade' in hist and 'TOTAL' in hist['grade']:
            show_report(hist, 'TOTAL', None)

168
169
170
171
172
173
    # only check gitlab if all tests pass
    if all(presults):
        newline()
        echo ("-"*max(10,width-5))
        echo ("Checking gitlab.")
        g = Git()
Alan Marchiori's avatar
Alan Marchiori committed
174
        if g.clean(cwd=labpath):
175
176
177
            success("All files are pushed to gitlab.")
        else:
            error("The remote git server is not consistent with your local path. Be sure to add/commit/push all local changes! Use 'git status' to see differences.")
Alan Marchiori's avatar
Alan Marchiori committed
178
            warn("\n"+g.status(cwd=labpath))
Alan Marchiori's avatar
daily    
Alan Marchiori committed
179
    #pprint(rubric)