Import pygrader, instead of pygrader.ENCODING.
[pygrader.git] / pygrader / storage.py
index 8b0c8b83192d95d101d3de90641287b26a9fd26f..b69b798a66f90f0fa7cafb8ece519a491174c1eb 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2012 W. Trevor King <wking@drexel.edu>
+# Copyright (C) 2012 W. Trevor King <wking@tremily.us>
 #
 # This file is part of pygrader.
 #
@@ -26,8 +26,8 @@ import re as _re
 import sys as _sys
 import time as _time
 
+import pygrader as _pygrader
 from . import LOG as _LOG
-from . import ENCODING as _ENCODING
 from .model.assignment import Assignment as _Assignment
 from .model.course import Course as _Course
 from .model.grade import Grade as _Grade
@@ -54,10 +54,12 @@ def load_course(basedir):
     []
     >>> print(course.robot)
     <Person Robot101>
+    >>> stub_course.cleanup()
     """
     _LOG.debug('loading course from {}'.format(basedir))
     config = _configparser.ConfigParser()
-    config.read([_os_path.join(basedir, 'course.conf')])
+    config.read([_os_path.join(basedir, 'course.conf')],
+                encoding=_pygrader.ENCODING)
     name = config.get('course', 'name')
     names = {'robot': [config.get('course', 'robot').strip()]}
     for option in ['assignments', 'professors', 'assistants', 'students']:
@@ -280,26 +282,32 @@ def load_person(name, data={}):
     return _Person(name=name, **kwargs)
 
 def load_grades(basedir, assignments, people):
+    "Load all grades in a course directory."
     for assignment in assignments:
         for person in people:
-            _LOG.debug('loading {} grade for {}'.format(assignment, person))
-            path = assignment_path(basedir, assignment, person)
-            gpath = _os_path.join(path, 'grade')
             try:
-                g = _load_grade(_io.open(gpath, 'r', encoding=_ENCODING),
-                                assignment, person)
+                yield load_grade(basedir, assignment, person)
             except IOError:
                 continue
-            #g.late = _os.stat(gpath).st_mtime > assignment.due
-            g.late = _os_path.exists(_os_path.join(path, 'late'))
-            npath = _os_path.join(path, 'notified')
-            if _os_path.exists(npath):
-                g.notified = newer(npath, gpath)
-            else:
-                g.notified = False
-            yield g
 
-def _load_grade(stream, assignment, person):
+def load_grade(basedir, assignment, person):
+    "Load a single grade from a course directory."
+    _LOG.debug('loading {} grade for {}'.format(assignment, person))
+    path = assignment_path(basedir, assignment, person)
+    gpath = _os_path.join(path, 'grade')
+    g = parse_grade(_io.open(gpath, 'r', encoding=_pygrader.ENCODING),
+                    assignment, person)
+    #g.late = _os.stat(gpath).st_mtime > assignment.due
+    g.late = _os_path.exists(_os_path.join(path, 'late'))
+    npath = _os_path.join(path, 'notified')
+    if _os_path.exists(npath):
+        g.notified = newer(npath, gpath)
+    else:
+        g.notified = False
+    return g
+
+def parse_grade(stream, assignment, person):
+    "Parse the points and comment from a grade stream."
     try:
         points = float(stream.readline())
     except ValueError:
@@ -334,6 +342,21 @@ def set_late(basedir, assignment, person):
     Lpath = _os_path.join(path, 'late')
     _touch(Lpath)
 
+def save_grade(basedir, grade):
+    "Save a grade into a course directory"
+    path = assignment_path(
+        basedir=basedir, assignment=grade.assignment, person=grade.student)
+    if not _os_path.isdir(path):
+        _os.makedirs(path)
+    gpath = _os_path.join(path, 'grade')
+    with _io.open(gpath, 'w', encoding=_pygrader.ENCODING) as f:
+        f.write('{}\n'.format(grade.points))
+        if grade.comment:
+            f.write('\n{}\n'.format(grade.comment.strip()))
+    set_notified(basedir=basedir, grade=grade)
+    set_late(
+        basedir=basedir, assignment=grade.assignment, person=grade.student)
+
 def _touch(path):
     """Touch a file (`path` is created if it doesn't already exist)