Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion grader/applications.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import tokenize

from . import (person, vector, util)
from .util import printff
from .util import (printff, write_csv_file)

DEBUG_MAPPINGS = False

Expand Down Expand Up @@ -724,3 +724,11 @@ def find_min_max(self):
min_ = min(scores)
items[item] = (max_-min_) / (maxsc-minsc)*100
return minsc, maxsc, items

def write_filtered_csv(self, filename, labels, attributes=('name', 'lastname', 'email')):
# Pick out the people to save to file
pool = self.filter(label=labels)
write_csv_file(filename,
attributes,
[[getattr(p, attr) for attr in attributes]
for p in pool])
131 changes: 66 additions & 65 deletions grader/grader.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import argparse
import collections
import enum
import itertools
import logging
import numbers
import operator
import os
import pathlib
import random
import re
Expand All @@ -29,6 +29,7 @@
list_of_float,
printf,
printff,
write_csv_file,
)

def ellipsize(s, width):
Expand Down Expand Up @@ -926,11 +927,11 @@ def do_rank(self, args):
.add_argument('-L', '--highlanders', action='store_true',
help='display statistics only for highlanders')
.add_argument('-l', '--labels',
help='display statistics only for people with label(s).'+
help='display statistics only for people with LABELS. '
'Multiple labels: INVITE,CONFIRMED or INVITE,-,DECLINED')
.add_argument('--edition', default='current',
help="edition for which we want the stats, e.g. '2010-trento'. "
"'all' means all editions 'current' (default) means the"
"'all' means all editions. 'current' (default) means the "
"latest one")
)

Expand Down Expand Up @@ -1161,6 +1162,27 @@ def do_save(self, args):
opts = self.save_options.parse_args(args.split())
self.applications.ini.save(opts.filename)

dumpcsv_options = (
cmd_completer.PagedArgumentParser('dumpcsv')
.add_argument('-l', '--labels',
help='only dump people with LABELS. '
'Multiple labels: INVITE,CONFIRMED or INVITE,-,DECLINED')
.add_argument('-a', '--attributes',
required=True,
help='comma-separated list of attributes to dump')
)


def do_dumpcsv(self, args):
opts = self.dumpcsv_options.parse_args(args.split())

labels = opts.labels.split(',') if opts.labels else []
attributes = opts.attributes.split(',')

# TODO: make the output name configurable?
self.applications.write_to_file('/tmp/grader.csv', labels, attributes)


def do_write(self, args):
"""Write lists of mailing recipients

Expand All @@ -1175,71 +1197,50 @@ def do_write(self, args):
"""
if args != '':
raise ValueError('no args please')
applications = self.applications

_write_file('list_confirmed.csv',
applications.filter(label=('CONFIRMED', '-', 'DECLINED', 'NEXT-YEAR')))

_write_file('list_invite.csv',
applications.filter(label=('INVITE', '-', 'DECLINED', 'CONFIRMED', 'NEXT-YEAR')))
_write_file('list_invite_reminder.csv',
applications.filter(label=('INVITE', '-', 'DECLINED', 'CONFIRMED', 'NEXT-YEAR')))
_write_file('list_overqualified.csv',
applications.filter(label=('OVERQUALIFIED', '-', 'CUSTOM-ANSWER')))
_write_file('list_custom_answer.csv',
applications.filter(label=('CUSTOM-ANSWER')))
self.applications.write_filtered_csv('list_confirmed.csv',
('CONFIRMED', '-', 'DECLINED', 'NEXT-YEAR'))

self.applications.write_filtered_csv('list_invite.csv',
('INVITE', '-', 'DECLINED', 'CONFIRMED', 'NEXT-YEAR'))

self.applications.write_filtered_csv('list_invite_reminder.csv',
('INVITE', '-', 'DECLINED', 'CONFIRMED', 'NEXT-YEAR'))

self.applications.write_filtered_csv('list_overqualified.csv',
('OVERQUALIFIED', '-', 'CUSTOM-ANSWER'))

self.applications.write_filtered_csv('list_custom_answer.csv',
('CUSTOM-ANSWER',))

# get all INVITESL? labels
all_labels = self.applications.all_labels()
invitesl = [label for label in all_labels
invitesl = [label for label in self.applications.all_labels()
if label.startswith('INVITESL')]
for i, sl_label in enumerate(invitesl):
_write_file_samelab(
'list_same_lab%d.csv'%(i+1),
applications.filter(label=(sl_label,'-', 'CONFIRMED', 'DECLINED', 'NEXT-YEAR')))
_write_file('list_shortlist.csv',
applications.filter(label=('SHORTLIST', '-', 'DECLINED', 'NEXT-YEAR', 'CONFIRMED', 'INVITE', *invitesl)))
_write_file('list_rejected.csv',
applications.filter(
label=('-', 'DECLINED', 'NEXT-YEAR', 'CONFIRMED', 'INVITE', 'SHORTLIST',
'OVERQUALIFIED', 'CUSTOM-ANSWER', *invitesl)))
_write_file('list_invite_nextyear.csv',
applications.filter(label=('NEXT-YEAR')))
_write_file('list_declined.csv',
applications.filter(label=('DECLINED', '-', 'NEXT-YEAR')))

def _write_file(filename, persons):
header = '$NAME$;$SURNAME$;$EMAIL$'
if os.path.exists(filename):
printf("'{}' already exists. We cannot overwrite it!", filename)
return
with open(filename, 'w') as f:
f.write(header + '\n')
i = -1
for i, person in enumerate(persons):
row = ';'.join((person.name, person.lastname, person.email))
f.write(row + '\n')
printf("'{}' written with header + {} rows", filename, i + 1)

def _write_file_samelab(filename, persons):
persons = list(persons)
if len(persons) == 0:
printf("No matching persons for '{}'. Check labels!", filename)
if os.path.exists(filename):
printf("'{}' already exists. We cannot overwrite it!", filename)
return
header = ';'.join('$%dNAME$;$%dSURNAME$'%(d+1,d+1) for d in range(len(persons))) + ';$EMAIL$'
with open(filename, 'w') as f:
f.write(header + '\n')
names = []
emails = []
i = -1
for i, person in enumerate(persons):
names.extend([person.name, person.lastname])
emails.append(person.email)
names = ';'.join(names)
emails = ','.join(emails)
f.write(names+';'+emails+'\n')
printf("'{}' written with header + {} entries", filename, i + 1)

self.applications.write_filtered_csv('list_shortlist.csv',
('SHORTLIST', '-', 'DECLINED', 'NEXT-YEAR', 'CONFIRMED', 'INVITE', *invitesl))

for i, sl_label in enumerate(invitesl, start=1):
persons = applications.filter(labels=(sl_label, '-', 'CONFIRMED', 'DECLINED', 'NEXT-YEAR'))

fields = [*itertools.chain.from_iterable(('{d}name', '{d}lastname') for d in range(1, len(persons) + 1)),
'email']

row = [*itertools.chain.from_iterable((p.name, p.lastname) for p in persons),
','.join(p.email for p in persons)]

write_csv_file('list_same_lab{i}.csv', fields, [row])

self.applications.write_filtered_csv('list_invite_nextyear.csv',
('NEXT-YEAR',))

self.applications.write_filtered_csv('list_rejected.csv',
('-', 'DECLINED', 'NEXT-YEAR', 'CONFIRMED', 'INVITE', 'SHORTLIST',
'OVERQUALIFIED', 'CUSTOM-ANSWER', *invitesl))

self.applications.write_filtered_csv('list_declined.csv',
('DECLINED', '-', 'NEXT-YEAR'))


class MissingRating(KeyError):
def __str__(self, *args):
Expand Down
3 changes: 3 additions & 0 deletions grader/test_applications.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ def test_applications_object(app):
assert len(app) == 3
assert len(app.people) == 3

alls = app.filter()
assert len(alls) == 3

vegans = app.filter(label = ['VEGAN'])
assert len(vegans) == 1
assert vegans.name == ['Jędrzej Marcin']
Expand Down
15 changes: 15 additions & 0 deletions grader/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,18 @@ def __init__(self, arg=None):

def __str__(self):
return ', '.join(self)


def write_csv_file(filename, fields, rows):
header = ';'.join(f'${field.upper()}$' for field in fields)
lines = [header]

for row in rows:
assert len(row) == len(fields)
lines += [';'.join(str(item) for item in row)]

with open(filename, 'wt') as fl:
fl.write('\n'.join(lines))
fl.write('\n')

printf(f'{filename!r} written with header + {len(rows)} rows')