From c38f1735aaa115192ae1c13d422e16bbe807abbc Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 20 Oct 2012 14:24:11 -0400 Subject: [PATCH] tabulate: work around missing NumPy. --- pygrader/tabulate.py | 72 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 16 deletions(-) diff --git a/pygrader/tabulate.py b/pygrader/tabulate.py index 4e21279..d8a962d 100644 --- a/pygrader/tabulate.py +++ b/pygrader/tabulate.py @@ -14,17 +14,67 @@ # You should have received a copy of the GNU General Public License along with # pygrader. If not, see . +import math as _math # for numpy workarounds and testing import sys as _sys +_numpy_import_error = None try: import numpy as _numpy -except ImportError: - raise # TODO work around +except ImportError as e: + _numpy = None + _numpy_import_error = e +from . import LOG as _LOG from .color import standard_colors as _standard_colors from .color import write_color as _write_color +def _mean(iterable): # missing-numpy workaround + """Return the mean of a list of items. + + >>> print(_mean([0,1,2,3,4,5,6])) + 3.0 + """ + length = len(iterable) + return sum(iterable) / float(length) + +def _std(iterable): # missing-numpy workaround + """Return the standard deviation of a list of items. + + >>> print(_std([0,1,2,3,4,5,6])) + 2.0 + """ + length = len(iterable) + m = _mean(iterable) + return _math.sqrt(sum((x-m)**2 for x in iterable) / length) + +if _numpy is None: + _statistics_container = list +else: + _statistics_container = _numpy.array + +def _statistic(iterabale, statistic): + """Calculate statistics on an list of numbers + """ + global _numpy_import_error + if _numpy_import_error: + assert _numpy_import_error is not None + _LOG.warning('error importing numpy, falling back to workarounds') + _LOG.warning(str(_numpy_import_error)) + _numpy_import_error = None + if stat == 'Mean': + if _numpy is None: # work around missing numpy + return _mean(iterable) + else: + return gs.mean() + elif stat == 'Std. Dev.': + if _numpy is None: # work around missing numpy + sval = _std(iterable) + else: + return gs.std() + else: + raise NotImplementedError(stat) + def tabulate(course, statistics=False, stream=None, use_color=None, **kwargs): """Return a table of student's grades to date """ @@ -69,23 +119,13 @@ def tabulate(course, statistics=False, stream=None, use_color=None, **kwargs): color = colors[(i+1)%len(colors)] grades = [g for g in course.grades if g.assignment == assignment] - gs = _numpy.array([g.points for g in grades]) - if stat == 'Mean': - sval = gs.mean() - elif stat == 'Std. Dev.': - sval = gs.std() - else: - raise NotImplementedError(stat) + gs = _statistics_container([g.points for g in grades]) + sval = _statistic(gs, statistic=stat) string = '\t{:.2f}'.format(sval) _write_color(string=string, color=color, stream=stream) if len(assignments) == len(course.assignments): - gs = _numpy.array([course.total(s) for s in students]) - if stat == 'Mean': - sval = gs.mean() - elif stat == 'Std. Dev.': - sval = gs.std() - else: - raise NotImplementedError(stat) + gs = _statistics_container([course.total(s) for s in students]) + sval = _statistic(gs, statistic=stat) string = '\t{}'.format(sval) color = colors[(i+2)%len(colors)] _write_color(string=string, color=color, stream=stream) -- 2.26.2