"""Exporters for faculties, departments, and other academics components. """ import csv import grok from cStringIO import StringIO from waeup.sirp.interfaces import ICSVExporter class FacultyExporter(grok.GlobalUtility): """Exporter for faculties. """ grok.implements(ICSVExporter) grok.name('faculties') #: Fieldnames considered by this exporter fields = ('code', 'title', 'title_prefix') def mangle_value(self, value, name, context=None): """Hook for mangling values in derived classes """ if isinstance(value, unicode): # CSV writers like byte streams better than unicode value = value.encode('utf-8') if value is None: # None is not really representable in CSV files value = '' return value def get_csv_writer(self, filepath=None): """Get a CSV dict writer instance open for writing. Returns a tuple (, ) where ```` is a :class:`csv.DictWriter` instance and outfile is the real file which is written to. The latter is important when writing to StringIO and can normally be ignored otherwise. The returned file will already be filled with the header row. """ if filepath is None: outfile = StringIO() else: outfile = open(filepath, 'wb') writer = csv.DictWriter(outfile, self.fields) writer.writerow(dict(zip(self.fields, self.fields))) # header return writer, outfile def write_item(self, faculty, writer): """Write a row into using `writer`. """ row = {} for name in self.fields: value = getattr(faculty, name, None) value = self.mangle_value(value, name, faculty) row[name] = value writer.writerow(row) return def close_outfile(self, filepath, outfile): """Close outfile. If filepath is None, the contents of outfile is returned. """ outfile.seek(0) if filepath is None: return outfile.read() outfile.close() return def export(self, faculties, filepath=None): """Export `faculties`, an iterable, as CSV file. If `filepath` is ``None``, a raw string with CSV data is returned. """ writer, outfile = self.get_csv_writer(filepath) for faculty in faculties: self.write_item(faculty, writer) return self.close_outfile(filepath, outfile) def export_all(self, site, filepath=None): """Export faculties in facultycontainer into filepath as CSV data. If `filepath` is ``None``, a raw string with CSV data is returned. """ writer, outfile = self.get_csv_writer(filepath) faculties = site.get('faculties', {}) return self.export(faculties.values(), filepath) for faculty in faculties.values(): self.write_item(faculty, writer) return self.close_outfile(filepath, outfile) class DepartmentExporter(FacultyExporter, grok.GlobalUtility): """Exporter for departments. """ grok.implements(ICSVExporter) grok.name('departments') #: Fieldnames considered by this exporter fields = ('code', 'faculty', 'title', 'title_prefix') def mangle_value(self, value, name, context=None): """Hook for mangling values in derived classes """ if name == 'faculty': value = getattr( getattr(context, '__parent__', None), 'code', None) return super(DepartmentExporter, self).mangle_value( value, name, context) def export_all(self, site, filepath=None): """Export faculties in facultycontainer into filepath as CSV data. If `filepath` is ``None``, a raw string with CSV data is returned. """ writer, outfile = self.get_csv_writer(filepath) faculties = site.get('faculties', {}) for faculty in faculties.values(): for department in faculty.values(): self.write_item(department, writer) return self.close_outfile(filepath, outfile) class CourseExporter(FacultyExporter, grok.GlobalUtility): """Exporter for courses. """ grok.implements(ICSVExporter) grok.name('courses') #: Fieldnames considered by this exporter fields = ('code', 'faculty', 'department', 'title', 'credits', 'passmark', 'semester') def mangle_value(self, value, name, context=None): """Hook for mangling values in derived classes """ if name == 'faculty': try: value = context.__parent__.__parent__.__parent__.code except AttributeError: value = None elif name == 'department': value = getattr( getattr(context, '__parent__', None), 'code', None) return super(CourseExporter, self).mangle_value( value, name, context) def export_all(self, site, filepath=None): """Export faculties in facultycontainer into filepath as CSV data. If `filepath` is ``None``, a raw string with CSV data is returned. """ writer, outfile = self.get_csv_writer(filepath) faculties = site.get('faculties', {}) for faculty in faculties.values(): for department in faculty.values(): for course in department.courses.values(): self.write_item(course, writer) return self.close_outfile(filepath, outfile)